blob: d6ca3e31592fbef697309c2f9e350a310fa1ff44 [file] [log] [blame]
/*
* (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
*----------------------------------------------------------------------
*/
#include "bios.h"
/*
* 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 !!
*/
.section .bios, "ax"
.code16
.org 0
/* a call to f000:0 should warmboot */
jmp realmode_reset
.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:
MAKE_BIOS_STACK
gs movw OFFS_VECTOR(%bp), %ax
cmpw $0x10, %ax
je Lint_10h
cmpw $0x11, %ax
je Lint_11h
cmpw $0x12, %ax
je Lint_12h
cmpw $0x13, %ax
je Lint_13h
cmpw $0x15, %ax
je Lint_15h
cmpw $0x16, %ax
je Lint_16h
cmpw $0x1a, %ax
je Lint_1ah
movw $0xffff, %ax
jmp Lout
Lint_10h: /* VGA BIOS services */
call bios_10h
jmp Lout
Lint_11h:
call bios_11h
jmp Lout
Lint_12h:
call bios_12h
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
Lint_1ah: /* PCI bios */
call bios_1ah
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:
RESTORE_CALLERS_STACK
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:
cs movw bios_equipment, %ax
gs movw %ax, OFFS_AX(%bp)
xorw %ax, %ax
ret
/*
************************************************************
* BIOS interrupt 12h -- Get Memory Size
************************************************************
*/
bios_12h:
cs movw ram_in_64kb_chunks, %ax
cmpw $0xa, %ax
ja b12_more_than_640k
shlw $6, %ax
jmp b12_return
b12_more_than_640k:
movw $0x280, %ax
b12_return:
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 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 */
cs movw ram_in_64kb_chunks, %ax
cmpw $0x100, %ax
ja e801_more_than_16mb
shlw $6, %ax /* multiply by 64 */
subw $0x400, %ax /* 1st meg does not count */
gs movw %ax, OFFS_AX(%bp) /* return memory size between 1M and 16M in 1kb chunks in AX and CX */
gs movw %ax, OFFS_CX(%bp)
gs movw $0, OFFS_BX(%bp) /* set BX and DX to 0*/
gs movw $0, 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
e801_more_than_16mb:
subw $0x100, %ax /* subtract 16MB */
gs movw $0x3c00, OFFS_AX(%bp) /* return 0x3c00 (16MB-1MB) 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 above 16MB */
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:
cs movw ram_in_64kb_chunks, %ax
cmpw $0x100, %ax
jna b88_not_more_than16
movw $0x100, %ax
b88_not_more_than16:
shlw $6, %ax
subw $0x400, %ax /* 1st meg does not count */
gs movw %ax, OFFS_AX(%bp) /* return number of kilobytes between 16MB and 16MB 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
/*
************************************************************
* BIOS interrupt 1ah -- PCI bios
************************************************************
*/
bios_1ah:
gs movw OFFS_AX(%bp), %ax
cmpb $0xb1, %ah
je Lfunc_b1h
movw $0xffff, %ax
ret
Lfunc_b1h:
call realmode_pci_bios
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