blob: f61fb6a50e7afb578fcf63f94bcd232af87cec39 [file] [log] [blame]
Kevin O'Connor392d2aa2013-09-15 00:14:28 -04001// Memory access to BIOS variables.
Kevin O'Connorf076a3e2008-02-25 22:25:15 -05002//
Kevin O'Connor392d2aa2013-09-15 00:14:28 -04003// Copyright (C) 2008-2013 Kevin O'Connor <kevin@koconnor.net>
Kevin O'Connorf076a3e2008-02-25 22:25:15 -05004//
Kevin O'Connorb1b7c2a2009-01-15 20:52:58 -05005// This file may be distributed under the terms of the GNU LGPLv3 license.
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -05006#ifndef __BIOSVAR_H
7#define __BIOSVAR_H
Kevin O'Connorf076a3e2008-02-25 22:25:15 -05008
Kevin O'Connord3140832012-05-13 22:46:12 -04009#include "config.h" // SEG_BDA
Kevin O'Connor392d2aa2013-09-15 00:14:28 -040010#include "farptr.h" // GET_FARVAR
Kevin O'Connor5d912262015-10-08 11:18:17 -040011#include "memmap.h" // SYMBOL
Kevin O'Connor392d2aa2013-09-15 00:14:28 -040012#include "std/bda.h" // struct bios_data_area_s
Kevin O'Connorb68ac712009-08-09 17:25:19 -040013
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050014
15/****************************************************************
Stefan Weil6bcacf72015-10-02 08:46:40 +020016 * Interrupt vector table
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050017 ****************************************************************/
18
Kevin O'Connor3d292132009-05-06 23:20:03 -040019#define GET_IVT(vector) \
20 GET_FARVAR(SEG_IVT, ((struct rmode_IVT *)0)->ivec[vector])
Kevin O'Connor9f985422009-09-09 11:34:39 -040021#define SET_IVT(vector, segoff) \
22 SET_FARVAR(SEG_IVT, ((struct rmode_IVT *)0)->ivec[vector], segoff)
Kevin O'Connor8c0e3722009-01-02 14:19:43 -050023
Kevin O'Connorcc9e1bf2010-07-28 21:31:38 -040024#define FUNC16(func) ({ \
25 ASSERT32FLAT(); \
26 extern void func (void); \
27 SEGOFF(SEG_BIOS, (u32)func - BUILD_BIOS_ADDR); \
28 })
29
Kevin O'Connor8c0e3722009-01-02 14:19:43 -050030
31/****************************************************************
32 * Bios Data Area (BDA)
33 ****************************************************************/
34
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050035// Accessor functions
Kevin O'Connor4b60c002008-02-25 22:29:55 -050036#define GET_BDA(var) \
Kevin O'Connor438f6352008-03-30 21:46:53 -040037 GET_FARVAR(SEG_BDA, ((struct bios_data_area_s *)0)->var)
Kevin O'Connor4b60c002008-02-25 22:29:55 -050038#define SET_BDA(var, val) \
Kevin O'Connor438f6352008-03-30 21:46:53 -040039 SET_FARVAR(SEG_BDA, ((struct bios_data_area_s *)0)->var, (val))
Kevin O'Connore51316d2012-06-10 09:09:22 -040040
41// Helper function to set the bits of the equipment_list_flags variable.
42static inline void set_equipment_flags(u16 clear, u16 set) {
43 u16 eqf = GET_BDA(equipment_list_flags);
44 SET_BDA(equipment_list_flags, (eqf & ~clear) | set);
45}
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050046
47
48/****************************************************************
49 * Extended Bios Data Area (EBDA)
50 ****************************************************************/
51
Kevin O'Connor49553a42009-05-17 10:31:34 -040052// The initial size and location of EBDA
53#define EBDA_SIZE_START \
54 DIV_ROUND_UP(sizeof(struct extended_bios_data_area_s), 1024)
55#define EBDA_SEGMENT_START \
Kevin O'Connorf416fe92009-09-24 20:51:55 -040056 FLATPTR_TO_SEG(BUILD_LOWRAM_END - EBDA_SIZE_START*1024)
Kevin O'Connor49553a42009-05-17 10:31:34 -040057
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050058// Accessor functions
Kevin O'Connor1ca05b02010-01-03 17:43:37 -050059static inline u16 get_ebda_seg(void) {
Kevin O'Connor08815372008-12-29 21:16:31 -050060 return GET_BDA(ebda_seg);
61}
Kevin O'Connor4d7c37e2008-12-26 23:50:17 -050062static inline struct extended_bios_data_area_s *
Kevin O'Connor1ca05b02010-01-03 17:43:37 -050063get_ebda_ptr(void)
Kevin O'Connor4d7c37e2008-12-26 23:50:17 -050064{
Kevin O'Connor52a300f2009-12-26 23:32:57 -050065 ASSERT32FLAT();
Kevin O'Connor35ae7262009-01-19 15:44:44 -050066 return MAKE_FLATPTR(get_ebda_seg(), 0);
Kevin O'Connor4d7c37e2008-12-26 23:50:17 -050067}
Kevin O'Connor4bc49972012-05-13 22:58:08 -040068#define GET_EBDA(eseg, var) \
Kevin O'Connor08815372008-12-29 21:16:31 -050069 GET_FARVAR(eseg, ((struct extended_bios_data_area_s *)0)->var)
Kevin O'Connor4bc49972012-05-13 22:58:08 -040070#define SET_EBDA(eseg, var, val) \
Kevin O'Connor08815372008-12-29 21:16:31 -050071 SET_FARVAR(eseg, ((struct extended_bios_data_area_s *)0)->var, (val))
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050072
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050073
74/****************************************************************
Kevin O'Connor15157a32008-12-13 11:10:37 -050075 * Global variables
76 ****************************************************************/
77
Kevin O'Connor871e0a02009-12-30 12:14:53 -050078#if MODE16 == 0 && MODESEGMENT == 1
79// In 32bit segmented mode %cs may not be readable and the code may be
80// relocated. The entry code sets up %gs with a readable segment and
81// the code offset can be determined by get_global_offset().
82#define GLOBAL_SEGREG GS
83static inline u32 __attribute_const get_global_offset(void) {
84 u32 ret;
85 asm(" calll 1f\n"
86 "1:popl %0\n"
87 " subl $1b, %0"
88 : "=r"(ret));
89 return ret;
90}
91#else
Kevin O'Connor8b267cb2009-01-19 19:25:21 -050092#define GLOBAL_SEGREG CS
Kevin O'Connor871e0a02009-12-30 12:14:53 -050093static inline u32 __attribute_const get_global_offset(void) {
94 return 0;
95}
96#endif
Kevin O'Connor1ca05b02010-01-03 17:43:37 -050097static inline u16 get_global_seg(void) {
Kevin O'Connor8b267cb2009-01-19 19:25:21 -050098 return GET_SEG(GLOBAL_SEGREG);
99}
Kevin O'Connor871e0a02009-12-30 12:14:53 -0500100#define GET_GLOBAL(var) \
101 GET_VAR(GLOBAL_SEGREG, *(typeof(&(var)))((void*)&(var) \
102 + get_global_offset()))
Kevin O'Connor52a300f2009-12-26 23:32:57 -0500103#if MODESEGMENT
Kevin O'Connor8f469b92010-02-28 01:28:11 -0500104#define GLOBALFLAT2GLOBAL(var) ((typeof(var))((void*)(var) - BUILD_BIOS_ADDR))
Kevin O'Connor77d227b2009-10-22 21:48:39 -0400105#else
Kevin O'Connor8f469b92010-02-28 01:28:11 -0500106#define GLOBALFLAT2GLOBAL(var) (var)
Kevin O'Connor77d227b2009-10-22 21:48:39 -0400107#endif
Kevin O'Connor8f469b92010-02-28 01:28:11 -0500108// Access a "flat" pointer known to point to the f-segment.
109#define GET_GLOBALFLAT(var) GET_GLOBAL(*GLOBALFLAT2GLOBAL(&(var)))
Kevin O'Connor15157a32008-12-13 11:10:37 -0500110
111
112/****************************************************************
Kevin O'Connor46b82622012-05-13 12:10:30 -0400113 * "Low" memory variables
114 ****************************************************************/
115
Kevin O'Connor5d912262015-10-08 11:18:17 -0400116#define SEG_LOW SYMBOL(_zonelow_seg)
Kevin O'Connor46b82622012-05-13 12:10:30 -0400117
118#if MODESEGMENT
119#define GET_LOW(var) GET_FARVAR(SEG_LOW, (var))
120#define SET_LOW(var, val) SET_FARVAR(SEG_LOW, (var), (val))
Kevin O'Connor5d912262015-10-08 11:18:17 -0400121#define LOWFLAT2LOW(var) ((typeof(var))((void*)(var) - SYMBOL(zonelow_base)))
Kevin O'Connor46b82622012-05-13 12:10:30 -0400122#else
123#define GET_LOW(var) (var)
124#define SET_LOW(var, val) do { (var) = (val); } while (0)
Kevin O'Connor4f6563e2012-05-19 22:42:51 -0400125#define LOWFLAT2LOW(var) (var)
Kevin O'Connor46b82622012-05-13 12:10:30 -0400126#endif
Kevin O'Connor4f6563e2012-05-19 22:42:51 -0400127#define GET_LOWFLAT(var) GET_LOW(*LOWFLAT2LOW(&(var)))
128#define SET_LOWFLAT(var, val) SET_LOW(*LOWFLAT2LOW(&(var)), (val))
Kevin O'Connor46b82622012-05-13 12:10:30 -0400129
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500130#endif // __BIOSVAR_H