Although the a20 functionality was originally implemented in the ps2 controller, that is just a historical artifact. It's a core feature of modern x86 cpus and the code is better located in the x86.h header.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/hw/ps2port.h | 14 +++----------- src/romlayout.S | 1 - src/system.c | 20 ++------------------ src/x86.h | 15 ++++++++++++++- 4 files changed, 19 insertions(+), 31 deletions(-)
diff --git a/src/hw/ps2port.h b/src/hw/ps2port.h index 2e6f25a..566073a 100644 --- a/src/hw/ps2port.h +++ b/src/hw/ps2port.h @@ -2,13 +2,11 @@ #ifndef __PS2PORT_H #define __PS2PORT_H
+#include "types.h" // u8 + #define PORT_PS2_DATA 0x0060 #define PORT_PS2_CTRLB 0x0061 #define PORT_PS2_STATUS 0x0064 -#define PORT_A20 0x0092 - -// PORT_A20 bitdefs -#define A20_ENABLE_BIT 0x02
// Standard commands. #define I8042_CMD_CTL_RCTR 0x0120 @@ -60,16 +58,10 @@ #define I8042_CTR_AUXDIS 0x20 #define I8042_CTR_XLATE 0x40
-#ifndef __ASSEMBLY__ - -#include "types.h" // u8 - -// functions +// ps2port.c void i8042_reboot(void); int ps2_kbd_command(int command, u8 *param); int ps2_mouse_command(int command, u8 *param); void ps2port_setup(void);
-#endif // !__ASSEMBLY__ - #endif // ps2port.h diff --git a/src/romlayout.S b/src/romlayout.S index 0651112..cca4e43 100644 --- a/src/romlayout.S +++ b/src/romlayout.S @@ -8,7 +8,6 @@ #include "asm-offsets.h" // BREGS_* #include "config.h" // CONFIG_* #include "entryfuncs.S" // ENTRY_* -#include "hw/ps2port.h" // PORT_A20 #include "hw/rtc.h" // CMOS_RESET_CODE #include "x86.h" // CR0_*
diff --git a/src/system.c b/src/system.c index 756dc31..bcf7e90 100644 --- a/src/system.c +++ b/src/system.c @@ -8,28 +8,12 @@ #include "biosvar.h" // GET_GLOBAL #include "bregs.h" // struct bregs #include "hw/pic.h" // pic_reset -#include "hw/ps2port.h" // PORT_A20 #include "malloc.h" // LegacyRamSize #include "memmap.h" // E820_RAM #include "output.h" // debug_enter #include "string.h" // memcpy_far #include "util.h" // handle_1553 -#include "x86.h" // inb - -// Use PS2 System Control port A to set A20 enable -static inline u8 -set_a20(u8 cond) -{ - // get current setting first - u8 newval, oldval = inb(PORT_A20); - if (cond) - newval = oldval | A20_ENABLE_BIT; - else - newval = oldval & ~A20_ENABLE_BIT; - outb(newval, PORT_A20); - - return (oldval & A20_ENABLE_BIT) != 0; -} +#include "x86.h" // set_a20
static void handle_152400(struct bregs *regs) @@ -48,7 +32,7 @@ handle_152401(struct bregs *regs) static void handle_152402(struct bregs *regs) { - regs->al = (inb(PORT_A20) & A20_ENABLE_BIT) != 0; + regs->al = get_a20(); set_code_success(regs); }
diff --git a/src/x86.h b/src/x86.h index 65f42b3..57773d2 100644 --- a/src/x86.h +++ b/src/x86.h @@ -14,6 +14,10 @@ #define CR0_NW (1<<29) // Not Write-through #define CR0_PE (1<<0) // Protection enable
+// PORT_A20 bitdefs +#define PORT_A20 0x0092 +#define A20_ENABLE_BIT 0x02 + #ifndef __ASSEMBLY__
#include "types.h" // u32 @@ -216,10 +220,19 @@ static inline void lgdt(struct descloc_s *desc) { asm("lgdtl %0" : : "m"(*desc) : "memory"); }
+static inline u8 get_a20(void) { + return (inb(PORT_A20) & A20_ENABLE_BIT) != 0; +} + +static inline u8 set_a20(u8 cond) { + u8 val = inb(PORT_A20); + outb((val & ~A20_ENABLE_BIT) | (cond ? A20_ENABLE_BIT : 0), PORT_A20); + return (val & A20_ENABLE_BIT) != 0; +} + // x86.c void cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
- #endif // !__ASSEMBLY__
#endif // x86.h
Previously, the a20 line would always be enabled and left on after call32_sloppy(). The setting should really be backed up and restored on each call.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/stacks.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/src/stacks.c b/src/stacks.c index 0d3eb77..b8d6e62 100644 --- a/src/stacks.c +++ b/src/stacks.c @@ -25,6 +25,7 @@ struct { u8 method; u8 cmosindex; + u8 a20; u16 ss, fs, gs; struct descloc_s gdt; } Call32Data VARLOW; @@ -174,6 +175,9 @@ call32_sloppy_prep(void) inb(PORT_CMOS_DATA); SET_LOW(Call32Data.cmosindex, cmosindex);
+ // Enable a20 and backup it's previous state + SET_LOW(Call32Data.a20, set_a20(1)); + // Backup ss/fs/gs and gdt SET_LOW(Call32Data.ss, GET_SEG(SS)); SET_LOW(Call32Data.fs, GET_SEG(FS)); @@ -201,6 +205,9 @@ call32_sloppy_post(void) SET_SEG(FS, GET_LOW(Call32Data.fs)); SET_SEG(GS, GET_LOW(Call32Data.gs));
+ // Restore a20 + set_a20(GET_LOW(Call32Data.a20)); + // Restore cmos index register outb(GET_LOW(Call32Data.cmosindex), PORT_CMOS_INDEX); inb(PORT_CMOS_DATA);