diff options
Diffstat (limited to 'lib_i386/bios.S')
-rw-r--r-- | lib_i386/bios.S | 443 |
1 files changed, 443 insertions, 0 deletions
diff --git a/lib_i386/bios.S b/lib_i386/bios.S new file mode 100644 index 0000000..2f5ea8c --- /dev/null +++ b/lib_i386/bios.S @@ -0,0 +1,443 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Based on msbios.c from rolo 1.6: + *---------------------------------------------------------------------- + * (C) Copyright 2000 + * Sysgo Real-Time Solutions GmbH + * Klein-Winternheim, Germany + *---------------------------------------------------------------------- + */ + +/* + * During it's initialization phase, before switching to protected + * mode, the Linux Kernel makes a few BIOS calls. This won't work + * if the board does not have a BIOS. + * + * This is a very minimalisic BIOS that supplies just enough + * functionality to keep the Linux Kernel happy. It is NOT + * a general purpose replacement for a real BIOS !! + */ + +#define OFFS_ES 0 +#define OFFS_GS 2 +#define OFFS_DS 4 +#define OFFS_DI 6 +#define OFFS_SI 8 +#define OFFS_BP 10 +#define OFFS_SP 12 +#define OFFS_BX 14 +#define OFFS_DX 16 +#define OFFS_CX 18 +#define OFFS_AX 20 +#define OFFS_VECTOR 22 +#define OFFS_IP 24 +#define OFFS_CS 26 +#define OFFS_FLAGS 28 + +#define SEGMENT 0x40 +#define STACK 0x800 /* stack at 0x40:0x800 -> 0x800 */ + +.section .bios, "ax" +.code16 +.org 0 + +.globl rm_int00 +rm_int00: + pushw $0 + jmp any_interrupt16 +.globl rm_int01 +rm_int01: + pushw $1 + jmp any_interrupt16 +.globl rm_int02 +rm_int02: + pushw $2 + jmp any_interrupt16 +.globl rm_int03 +rm_int03: + pushw $3 + jmp any_interrupt16 +.globl rm_int04 +rm_int04: + pushw $4 + jmp any_interrupt16 +.globl rm_int05 +rm_int05: + pushw $5 + jmp any_interrupt16 +.globl rm_int06 +rm_int06: + pushw $6 + jmp any_interrupt16 +.globl rm_int07 +rm_int07: + pushw $7 + jmp any_interrupt16 +.globl rm_int08 +rm_int08: + pushw $8 + jmp any_interrupt16 +.globl rm_int09 +rm_int09: + pushw $9 + jmp any_interrupt16 +.globl rm_int0a +rm_int0a: + pushw $10 + jmp any_interrupt16 +.globl rm_int0b +rm_int0b: + pushw $11 + jmp any_interrupt16 +.globl rm_int0c +rm_int0c: + pushw $12 + jmp any_interrupt16 +.globl rm_int0d +rm_int0d: + pushw $13 + jmp any_interrupt16 +.globl rm_int0e +rm_int0e: + pushw $14 + jmp any_interrupt16 +.globl rm_int0f +rm_int0f: + pushw $15 + jmp any_interrupt16 +.globl rm_int10 +rm_int10: + pushw $16 + jmp any_interrupt16 +.globl rm_int11 +rm_int11: + pushw $17 + jmp any_interrupt16 +.globl rm_int12 +rm_int12: + pushw $18 + jmp any_interrupt16 +.globl rm_int13 +rm_int13: + pushw $19 + jmp any_interrupt16 +.globl rm_int14 +rm_int14: + pushw $20 + jmp any_interrupt16 +.globl rm_int15 +rm_int15: + pushw $21 + jmp any_interrupt16 +.globl rm_int16 +rm_int16: + pushw $22 + jmp any_interrupt16 +.globl rm_int17 +rm_int17: + pushw $23 + jmp any_interrupt16 +.globl rm_int18 +rm_int18: + pushw $24 + jmp any_interrupt16 +.globl rm_int19 +rm_int19: + pushw $25 + jmp any_interrupt16 +.globl rm_int1a +rm_int1a: + pushw $26 + jmp any_interrupt16 +.globl rm_int1b +rm_int1b: + pushw $27 + jmp any_interrupt16 +.globl rm_int1c +rm_int1c: + pushw $28 + jmp any_interrupt16 +.globl rm_int1d +rm_int1d: + pushw $29 + jmp any_interrupt16 +.globl rm_int1e +rm_int1e: + pushw $30 + jmp any_interrupt16 +.globl rm_int1f +rm_int1f: + pushw $31 + jmp any_interrupt16 +.globl rm_def_int +rm_def_int: + iret + + + /* + * All interrupt jumptable entries jump to here + * after pushing the interrupt vector number onto the + * stack. + */ +any_interrupt16: + pusha /* save general registers */ + pushw %ds /* save some segments */ + pushw %gs + pushw %es + pushw %ss /* save callers stack segment .. */ + popw %gs /* ... in gs */ + movw $SEGMENT,%ax /* setup my segments */ + movw %ax,%ds + movw %ax,%es + movw %ax,%ss + movw %sp,%bp + movw $STACK,%sp /* setup BIOS stackpointer */ + +gs movw OFFS_VECTOR(%bp), %ax + cmpw $0x10, %ax + je Lint_10h + cmpw $0x11, %ax + je Lint_11h + cmpw $0x13, %ax + je Lint_13h + cmpw $0x15, %ax + je Lint_15h + cmpw $0x16, %ax + je Lint_16h + movw $0xffff, %ax + jmp Lout +Lint_10h: /* VGA BIOS services */ + call bios_10h + jmp Lout +Lint_11h: + call bios_11h + jmp Lout +Lint_13h: /* BIOS disk services */ + call bios_13h + jmp Lout +Lint_15h: /* Misc. BIOS services */ + call bios_15h + jmp Lout +Lint_16h: /* keyboard services */ + call bios_16h + jmp Lout +Lout: + cmpw $0, %ax + je Lhandeled + + /* Insert code for unhandeled INTs here. + * + * ROLO prints a message to the console + * (we could do that but then we're in 16bit mode + * so we'll have to get back into 32bit mode + * to use the console I/O routines (if we do this + * we shuls make int 0x10 and int 0x16 work as well)) + */ +Lhandeled: + + pushw %gs /* restore callers stack segment */ + popw %ss + movw %bp,%sp /* restore stackpointer */ + + popw %es /* restore segment selectors */ + popw %gs + popw %ds + + popa /* restore GP registers */ + addw $2,%sp /* dump vector number */ + iret /* return from interrupt */ + + +/* + ************************************************************ + * BIOS interrupt 10h -- VGA services + ************************************************************ + */ +bios_10h: +gs movw OFFS_AX(%bp), %ax + shrw $8, %ax + cmpw $0x3, %ax + je Lcur_pos + cmpw $0xf, %ax + je Lvid_state + cmpw $0x12, %ax + je Lvid_cfg + movw $0xffff, %ax + ret +Lcur_pos: /* Read Cursor Position and Size */ +gs movw $0, OFFS_CX(%bp) +gs movw $0, OFFS_DX(%bp) + xorw %ax, %ax + ret +Lvid_state: /* Get Video State */ +gs movw $(80 << 8|0x03), OFFS_AX(%bp) /* 80 columns, 80x25, 16 colors */ +gs movw $0, OFFS_BX(%bp) + xorw %ax, %ax + ret +Lvid_cfg: /* Video Subsystem Configuration (EGA/VGA) */ +gs movw $0x10, OFFS_BX(%bp) /* indicate CGA/MDA/HGA */ + xorw %ax, %ax + ret + + +/* + ************************************************************ + * BIOS interrupt 11h -- Equipment determination + ************************************************************ + */ + +bios_11h: + movw bios_equipment, %ax +gs movw %ax, OFFS_AX(%bp) + xorw %ax, %ax + ret + + +/* + ************************************************************ + * BIOS interrupt 13h -- Disk services + ************************************************************ + */ +bios_13h: +gs movw OFFS_AX(%bp), %ax + shrw $8, %ax + cmpw $0x15, %ax + je Lfunc_15h + movw $0xffff, %ax + ret +Lfunc_15h: +gs movw OFFS_AX(%bp), %ax + andw $0xff, %ax /* return AH=0->drive not present */ +gs movw %ax, OFFS_AX(%bp) + xorw %ax, %ax + ret + + + +/* + *********************************************************** + * BIOS interrupt 15h -- Miscellaneous services + *********************************************************** + */ +bios_15h: +gs movw OFFS_AX(%bp), %ax + shrw $8, %ax + cmpw $0xc0, %ax + je Lfunc_c0h + cmpw $0xe8, %ax + je Lfunc_e8h + cmpw $0x88, %ax + je Lfunc_88h + movw $0xffff, %ax + ret + +Lfunc_c0h: /* Return System Configuration Parameters (PS2 only) */ +gs movw OFFS_FLAGS(%bp), %ax + orw $1, %ax /* return carry -- function not supported */ +gs movw %ax, OFFS_FLAGS(%bp) + xorw %ax, %ax + ret + +Lfunc_e8h: +gs movw OFFS_AX(%bp), %ax + andw $0xff, %ax + cmpw $1, %ax + je Lfunc_e801h +gs movw OFFS_FLAGS(%bp), %ax + orw $1, %ax /* return carry -- function not supported */ +gs movw %ax, OFFS_FLAGS(%bp) + xorw %ax, %ax + ret + +Lfunc_e801h: /* Get memory size for >64M Configurations */ + movw $ram_in_64kb_chunks, %ax + cmpw $256, %ax + ja Lmore_than_16mb + shlw $6, %ax /* multiply by 64 */ +gs movw %ax, OFFS_AX(%bp) /* return memory size in 1kb chunks in AX and CX */ +gs movw %ax, OFFS_CX(%bp) + xorw %ax, %ax +gs movw %ax, OFFS_BX(%bp) /* set BX and DX to 0*/ +gs movw %ax, OFFS_DX(%bp) +gs movw OFFS_FLAGS(%bp), %ax + andw $0xfffe, %ax /* clear carry -- function succeeded */ +gs movw %ax, OFFS_FLAGS(%bp) + xorw %ax, %ax + ret + +Lmore_than_16mb: + subw $0x100, %ax /* subtract 16MB */ + +gs movw $0x3c00, OFFS_AX(%bp) /* return 0x3c00 (16MB-384k) in AX and CX */ +gs movw $0x3c00, OFFS_CX(%bp) +gs movw %ax, OFFS_BX(%bp) /* set BX and DX to number of 64kb chunks - 256 */ +gs movw %ax, OFFS_DX(%bp) + +gs movw OFFS_FLAGS(%bp), %ax + andw $0xfffe, %ax /* clear carry -- function succeeded */ +gs movw %ax, OFFS_FLAGS(%bp) + xorw %ax, %ax + ret + +Lfunc_88h: + movw ram_in_64kb_chunks, %ax + subw $16, %ax + shlw $6, %ax + +gs movw %ax, OFFS_AX(%bp) /* return number of kilobytes in ax */ + +gs movw OFFS_FLAGS(%bp), %ax + andw $0xfffe, %ax /* clear carry -- function succeeded */ +gs movw %ax, OFFS_FLAGS(%bp) + + xorw %ax, %ax + ret + + +/* + ************************************************************ + * BIOS interrupt 16h -- keyboard services + ************************************************************ + */ +bios_16h: +gs movw OFFS_AX(%bp), %ax + shrw $8, %ax + cmpw $0x03, %ax + je Lfunc_03h + movw $0xffff, %ax + ret +Lfunc_03h: + xorw %ax, %ax /* do nothing -- function not supported */ + ret + + +.globl ram_in_64kb_chunks +ram_in_64kb_chunks: + .word 0 + +.globl bios_equipment +bios_equipment: + .word 0 + |