This code is pretty old and we want to support only 32-bit systems now. Signed-off-by: Simon Glass <sjg@chromium.org> Acked-by: Graeme Russ <graeme.russ@gmail.com>master
parent
588a13f742
commit
96dfc0633a
@ -1,36 +0,0 @@ |
||||
/*
|
||||
* (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 |
||||
*/ |
||||
|
||||
#ifndef __ASM_REALMODE_H_ |
||||
#define __ASM_REALMODE_H_ |
||||
#include <asm/ptrace.h> |
||||
|
||||
extern ulong __realmode_start; |
||||
extern ulong __realmode_size; |
||||
extern char realmode_enter; |
||||
|
||||
int bios_setup(void); |
||||
int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out); |
||||
int enter_realmode_int(u8 lvl, struct pt_regs *in, struct pt_regs *out); |
||||
|
||||
#endif |
@ -1,569 +0,0 @@ |
||||
/* |
||||
* (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
|
||||
.hidden rm_int00
|
||||
.type rm_int00, @function
|
||||
rm_int00: |
||||
pushw $0 |
||||
jmp any_interrupt16 |
||||
.globl rm_int01
|
||||
.hidden rm_int01
|
||||
.type rm_int01, @function
|
||||
rm_int01: |
||||
pushw $1 |
||||
jmp any_interrupt16 |
||||
.globl rm_int02
|
||||
.hidden rm_int02
|
||||
.type rm_int02, @function
|
||||
rm_int02: |
||||
pushw $2 |
||||
jmp any_interrupt16 |
||||
.globl rm_int03
|
||||
.hidden rm_int03
|
||||
.type rm_int03, @function
|
||||
rm_int03: |
||||
pushw $3 |
||||
jmp any_interrupt16 |
||||
.globl rm_int04
|
||||
.hidden rm_int04
|
||||
.type rm_int04, @function
|
||||
rm_int04: |
||||
pushw $4 |
||||
jmp any_interrupt16 |
||||
.globl rm_int05
|
||||
.hidden rm_int05
|
||||
.type rm_int05, @function
|
||||
rm_int05: |
||||
pushw $5 |
||||
jmp any_interrupt16 |
||||
.globl rm_int06
|
||||
.hidden rm_int06
|
||||
.type rm_int06, @function
|
||||
rm_int06: |
||||
pushw $6 |
||||
jmp any_interrupt16 |
||||
.globl rm_int07
|
||||
.hidden rm_int07
|
||||
.type rm_int07, @function
|
||||
rm_int07: |
||||
pushw $7 |
||||
jmp any_interrupt16 |
||||
.globl rm_int08
|
||||
.hidden rm_int08
|
||||
.type rm_int08, @function
|
||||
rm_int08: |
||||
pushw $8 |
||||
jmp any_interrupt16 |
||||
.globl rm_int09
|
||||
.hidden rm_int09
|
||||
.type rm_int09, @function
|
||||
rm_int09: |
||||
pushw $9 |
||||
jmp any_interrupt16 |
||||
.globl rm_int0a
|
||||
.hidden rm_int0a
|
||||
.type rm_int0a, @function
|
||||
rm_int0a: |
||||
pushw $10 |
||||
jmp any_interrupt16 |
||||
.globl rm_int0b
|
||||
.hidden rm_int0b
|
||||
.type rm_int0b, @function
|
||||
rm_int0b: |
||||
pushw $11 |
||||
jmp any_interrupt16 |
||||
.globl rm_int0c
|
||||
.hidden rm_int0c
|
||||
.type rm_int0c, @function
|
||||
rm_int0c: |
||||
pushw $12 |
||||
jmp any_interrupt16 |
||||
.globl rm_int0d
|
||||
.hidden rm_int0d
|
||||
.type rm_int0d, @function
|
||||
rm_int0d: |
||||
pushw $13 |
||||
jmp any_interrupt16 |
||||
.globl rm_int0e
|
||||
.hidden rm_int0e
|
||||
.type rm_int0e, @function
|
||||
rm_int0e: |
||||
pushw $14 |
||||
jmp any_interrupt16 |
||||
.globl rm_int0f
|
||||
.hidden rm_int0f
|
||||
.type rm_int0f, @function
|
||||
rm_int0f: |
||||
pushw $15 |
||||
jmp any_interrupt16 |
||||
.globl rm_int10
|
||||
.hidden rm_int10
|
||||
.type rm_int10, @function
|
||||
rm_int10: |
||||
pushw $16 |
||||
jmp any_interrupt16 |
||||
.globl rm_int11
|
||||
.hidden rm_int11
|
||||
.type rm_int11, @function
|
||||
rm_int11: |
||||
pushw $17 |
||||
jmp any_interrupt16 |
||||
.globl rm_int12
|
||||
.hidden rm_int12
|
||||
.type rm_int12, @function
|
||||
rm_int12: |
||||
pushw $18 |
||||
jmp any_interrupt16 |
||||
.globl rm_int13
|
||||
.hidden rm_int13
|
||||
.type rm_int13, @function
|
||||
rm_int13: |
||||
pushw $19 |
||||
jmp any_interrupt16 |
||||
.globl rm_int14
|
||||
.hidden rm_int14
|
||||
.type rm_int14, @function
|
||||
rm_int14: |
||||
pushw $20 |
||||
jmp any_interrupt16 |
||||
.globl rm_int15
|
||||
.hidden rm_int15
|
||||
.type rm_int15, @function
|
||||
rm_int15: |
||||
pushw $21 |
||||
jmp any_interrupt16 |
||||
.globl rm_int16
|
||||
.hidden rm_int16
|
||||
.type rm_int16, @function
|
||||
rm_int16: |
||||
pushw $22 |
||||
jmp any_interrupt16 |
||||
.globl rm_int17
|
||||
.hidden rm_int17
|
||||
.type rm_int17, @function
|
||||
rm_int17: |
||||
pushw $23 |
||||
jmp any_interrupt16 |
||||
.globl rm_int18
|
||||
.hidden rm_int18
|
||||
.type rm_int18, @function
|
||||
rm_int18: |
||||
pushw $24 |
||||
jmp any_interrupt16 |
||||
.globl rm_int19
|
||||
.hidden rm_int19
|
||||
.type rm_int19, @function
|
||||
rm_int19: |
||||
pushw $25 |
||||
jmp any_interrupt16 |
||||
.globl rm_int1a
|
||||
.hidden rm_int1a
|
||||
.type rm_int1a, @function
|
||||
rm_int1a: |
||||
pushw $26 |
||||
jmp any_interrupt16 |
||||
.globl rm_int1b
|
||||
.hidden rm_int1b
|
||||
.type rm_int1b, @function
|
||||
rm_int1b: |
||||
pushw $27 |
||||
jmp any_interrupt16 |
||||
.globl rm_int1c
|
||||
.hidden rm_int1c
|
||||
.type rm_int1c, @function
|
||||
rm_int1c: |
||||
pushw $28 |
||||
jmp any_interrupt16 |
||||
.globl rm_int1d
|
||||
.hidden rm_int1d
|
||||
.type rm_int1d, @function
|
||||
rm_int1d: |
||||
pushw $29 |
||||
jmp any_interrupt16 |
||||
.globl rm_int1e
|
||||
.hidden rm_int1e
|
||||
.type rm_int1e, @function
|
||||
rm_int1e: |
||||
pushw $30 |
||||
jmp any_interrupt16 |
||||
.globl rm_int1f
|
||||
.hidden rm_int1f
|
||||
.type rm_int1f, @function
|
||||
rm_int1f: |
||||
pushw $31 |
||||
jmp any_interrupt16 |
||||
.globl rm_def_int
|
||||
.hidden rm_def_int
|
||||
.type rm_def_int, @function
|
||||
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 should make |
||||
* int 0x10 and int 0x16 work as well) |
||||
*/ |
||||
Lhandeled: |
||||
RESTORE_CALLERS_STACK |
||||
|
||||
/* dump vector number */ |
||||
addw $2,%sp |
||||
|
||||
/* return from interrupt */ |
||||
iret |
||||
|
||||
/* |
||||
************************************************************ |
||||
* 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 - 80 columns, 80x25, 16 colors */ |
||||
gs movw $(80 << 8|0x03), OFFS_AX(%bp) |
||||
gs movw $0, OFFS_BX(%bp) |
||||
xorw %ax, %ax |
||||
ret |
||||
Lvid_cfg: |
||||
/* Video Subsystem Configuration (EGA/VGA) - indicate CGA/MDA/HGA */ |
||||
gs movw $0x10, OFFS_BX(%bp) |
||||
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: |
||||
/* return number of kilobytes in ax */ |
||||
gs movw %ax, OFFS_AX(%bp) |
||||
|
||||
gs movw OFFS_FLAGS(%bp), %ax |
||||
|
||||
/* clear carry -- function succeeded */ |
||||
andw $0xfffe, %ax |
||||
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 |
||||
|
||||
/* return AH=0->drive not present */ |
||||
andw $0x00ff, %ax |
||||
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 |
||||
|
||||
/* return carry -- function not supported */ |
||||
orw $1, %ax |
||||
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 |
||||
|
||||
/* return carry -- function not supported */ |
||||
orw $1, %ax |
||||
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 |
||||
|
||||
/* multiply by 64 */ |
||||
shlw $6, %ax |
||||
|
||||
/* 1st meg does not count */ |
||||
subw $0x400, %ax |
||||
|
||||
/* return memory size between 1M and 16M in 1kb chunks in AX and CX */ |
||||
gs movw %ax, OFFS_AX(%bp) |
||||
gs movw %ax, OFFS_CX(%bp) |
||||
|
||||
/* set BX and DX to 0*/ |
||||
gs movw $0, OFFS_BX(%bp) |
||||
gs movw $0, OFFS_DX(%bp) |
||||
gs movw OFFS_FLAGS(%bp), %ax |
||||
|
||||
/* clear carry -- function succeeded */ |
||||
andw $0xfffe, %ax |
||||
gs movw %ax, OFFS_FLAGS(%bp) |
||||
xorw %ax, %ax |
||||
ret |
||||
|
||||
e801_more_than_16mb: |
||||
/* subtract 16MB */ |
||||
subw $0x100, %ax |
||||
|
||||
/* return 0x3c00 (16MB-1MB) in AX and CX */ |
||||
gs movw $0x3c00, OFFS_AX(%bp) |
||||
gs movw $0x3c00, OFFS_CX(%bp) |
||||
|
||||
/* set BX and DX to number of 64kb chunks above 16MB */ |
||||
gs movw %ax, OFFS_BX(%bp) |
||||
gs movw %ax, OFFS_DX(%bp) |
||||
|
||||
gs movw OFFS_FLAGS(%bp), %ax |
||||
|
||||
/* clear carry -- function succeeded */ |
||||
andw $0xfffe, %ax |
||||
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 |
||||
|
||||
/* 1st meg does not count */ |
||||
subw $0x400, %ax |
||||
|
||||
/* return number of kilobytes between 16MB and 16MB in ax */ |
||||
gs movw %ax, OFFS_AX(%bp) |
||||
|
||||
gs movw OFFS_FLAGS(%bp), %ax |
||||
|
||||
/* clear carry -- function succeeded */ |
||||
andw $0xfffe, %ax |
||||
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: |
||||
/* do nothing -- function not supported */ |
||||
xorw %ax, %ax |
||||
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 |
||||
|
||||
/* do nothing -- function not supported */ |
||||
xorw %ax, %ax |
||||
ret |
||||
|
||||
|
||||
.globl ram_in_64kb_chunks
|
||||
.hidden ram_in_64kb_chunks
|
||||
.type ram_in_64kb_chunks, @function
|
||||
ram_in_64kb_chunks: |
||||
.word 0
|
||||
|
||||
.globl bios_equipment
|
||||
.hidden bios_equipment
|
||||
.type bios_equipment, @function
|
||||
bios_equipment: |
||||
.word 0
|
@ -1,447 +0,0 @@ |
||||
/* |
||||
* (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 |
||||
*/ |
||||
|
||||
/* |
||||
* x86 realmode assembly implementation of a PCI BIOS |
||||
* for platforms that use one PCI hose and configuration |
||||
* access type 1. (The common case for low-end PC's) |
||||
*/ |
||||
|
||||
#include "bios.h" |
||||
|
||||
#define PCI_BIOS_DEBUG |
||||
|
||||
.section .bios, "ax" |
||||
.code16 |
||||
.globl realmode_pci_bios_call_entry
|
||||
.hidden realmode_pci_bios_call_entry
|
||||
.type realmode_pci_bios_call_entry, @function
|
||||
realmode_pci_bios_call_entry: |
||||
MAKE_BIOS_STACK |
||||
call realmode_pci_bios |
||||
RESTORE_CALLERS_STACK |
||||
ret |
||||
|
||||
|
||||
.globl realmode_pci_bios
|
||||
realmode_pci_bios: |
||||
gs movw OFFS_AX(%bp), %ax |
||||
cmpb $1, %al |
||||
je pci_bios_present |
||||
cmpb $2, %al |
||||
je pci_bios_find_device |
||||
cmpb $3, %al |
||||
je pci_bios_find_class |
||||
cmpb $6, %al |
||||
je pci_bios_generate_special_cycle |
||||
cmpb $8, %al |
||||
je pci_bios_read_cfg_byte |
||||
cmpb $9, %al |
||||
je pci_bios_read_cfg_word |
||||
cmpb $10, %al |
||||
je pci_bios_read_cfg_dword |
||||
cmpb $11, %al |
||||
je pci_bios_write_cfg_byte |
||||
cmpb $12, %al |
||||
je pci_bios_write_cfg_word |
||||
cmpb $13, %al |
||||
je pci_bios_write_cfg_dword |
||||
cmpb $14, %al |
||||
je pci_bios_get_irq_routing |
||||
cmpb $15, %al |
||||
je pci_bios_set_irq |
||||
jmp unknown_function |
||||
|
||||
/*****************************************************************************/ |
||||
|
||||
pci_bios_present: |
||||
#ifdef PCI_BIOS_DEBUG |
||||
cs incl num_pci_bios_present |
||||
#endif |
||||
movl $0x20494350, %eax |
||||
gs movl %eax, OFFS_EDX(%bp) |
||||
|
||||
/* We support cfg type 1 version 2.10 */ |
||||
movb $0x01, %al |
||||
gs movb %al, OFFS_AL(%bp) |
||||
movw $0x0210, %ax |
||||
gs movw %ax, OFFS_BX(%bp) |
||||
|
||||
/* last bus number */ |
||||
cs movb pci_last_bus, %al |
||||
gs movb %al, OFFS_CL(%bp) |
||||
jmp clear_carry |
||||
|
||||
/*****************************************************************************/ |
||||
|
||||
/* device 0-31, function 0-7 */ |
||||
pci_bios_find_device: |
||||
#ifdef PCI_BIOS_DEBUG |
||||
cs incl num_pci_bios_find_device |
||||
#endif |
||||
gs movw OFFS_CX(%bp), %di |
||||
shll $16, %edi |
||||
gs movw OFFS_DX(%bp), %di |
||||
/* edi now holds device in upper 16 bits and vendor in lower 16 bits */ |
||||
|
||||
gs movw OFFS_SI(%bp), %si |
||||
|
||||
/* start at bus 0 dev 0 function 0 */ |
||||
xorw %bx, %bx |
||||
pfd_loop: |
||||
/* dword 0 is vendor/device */ |
||||
xorw %ax, %ax |
||||
call __pci_bios_select_register |
||||
movw $0xcfc, %dx |
||||
inl %dx, %eax |
||||
|
||||
/* our device ? */ |
||||
cmpl %edi, %eax |
||||
je pfd_found_one |
||||
pfd_next_dev: |
||||
/* check for multi function devices */ |
||||
movw %bx, %ax |
||||
andw $3, %ax |
||||
jnz pfd_function_not_zero |
||||
movw $0x000c, %ax |
||||
call __pci_bios_select_register |
||||
movw $0xcfe, %dx |
||||
inb %dx, %al |
||||
andb $0x80, %al |
||||
jz pfd_not_multi_function |
||||
pfd_function_not_zero: |
||||
/* next function, overflows in to device number, then bus number */ |
||||
incw %bx |
||||
jmp pfd_check_bus |
||||
|
||||
pfd_not_multi_function: |
||||
/* remove function bits */ |
||||
andw $0xfff8, %bx |
||||
|
||||
/* next device, overflows in to bus number */ |
||||
addw $0x0008, %bx |
||||
pfd_check_bus: |
||||
cs movb pci_last_bus, %ah |
||||
cmpb %ah, %bh |
||||
ja pfd_not_found |
||||
jmp pfd_loop |
||||
pfd_found_one: |
||||
decw %si |
||||
js pfd_done |
||||
jmp pfd_next_dev |
||||
|
||||
pfd_done: |
||||
gs movw %bx, OFFS_BX(%bp) |
||||
jmp clear_carry |
||||
|
||||
pfd_not_found: |
||||
/* device not found */ |
||||
movb $0x86, %ah |
||||
jmp set_carry |
||||
|
||||
/*****************************************************************************/ |
||||
|
||||
pci_bios_find_class: |
||||
#ifdef PCI_BIOS_DEBUG |
||||
cs incl num_pci_bios_find_class |
||||
#endif |
||||
gs movl OFFS_ECX(%bp), %edi |
||||
|
||||
/* edi now holds class-code in lower 24 bits */ |
||||
andl $0x00ffffff, %edi |
||||
gs movw OFFS_SI(%bp), %si |
||||
|
||||
/* start at bus 0 dev 0 function 0 */ |
||||
xorw %bx, %bx |
||||
pfc_loop: |
||||
/* dword 8 is class-code high 24bits */ |
||||
movw $8, %ax |
||||
call __pci_bios_select_register |
||||
movw $0xcfc, %dx |
||||
inl %dx, %eax |
||||
shrl $8, %eax |
||||
andl $0x00ffffff, %eax |
||||
|
||||
/* our device ? */ |
||||
cmpl %edi, %eax |
||||
je pfc_found_one |
||||
pfc_next_dev: |
||||
/* check for multi function devices */ |
||||
andw $3, %bx |
||||
jnz pfc_function_not_zero |
||||
movw $0x000c, %ax |
||||
call __pci_bios_select_register |
||||
movw $0xcfe, %dx |
||||
inb %dx, %al |
||||
andb $0x80, %al |
||||
jz pfc_not_multi_function |
||||
pfc_function_not_zero: |
||||
/* next function, overflows in to device number, then bus number */ |
||||
incw %bx |
||||
jmp pfc_check_bus |
||||
|
||||
pfc_not_multi_function: |
||||
/* remove function bits */ |
||||
andw $0xfff8, %bx |
||||
|
||||
/* next device, overflows in to bus number */ |
||||
addw $0x0008, %bx |
||||
pfc_check_bus: |
||||
cs movb pci_last_bus, %ah |
||||
cmpb %ah, %bh |
||||
ja pfc_not_found |
||||
jmp pfc_loop |
||||
pfc_found_one: |
||||
decw %si |
||||
js pfc_done |
||||
jmp pfc_next_dev |
||||
|
||||
pfc_done: |
||||
gs movw %bx, OFFS_BX(%bp) |
||||
jmp clear_carry |
||||
|
||||
pfc_not_found: |
||||
/* device not found */ |
||||
movb $0x86, %ah |
||||
jmp set_carry |
||||
|
||||
/*****************************************************************************/ |
||||
|
||||
pci_bios_generate_special_cycle: |
||||
#ifdef PCI_BIOS_DEBUG |
||||
cs incl num_pci_bios_generate_special_cycle |
||||
#endif |
||||
/* function not supported */ |
||||
movb $0x81, %ah |
||||
jmp set_carry |
||||
|
||||
/*****************************************************************************/ |
||||
|
||||
pci_bios_read_cfg_byte: |
||||
#ifdef PCI_BIOS_DEBUG |
||||
cs incl num_pci_bios_read_cfg_byte |
||||
#endif |
||||
call pci_bios_select_register |
||||
gs movw OFFS_DI(%bp), %dx |
||||
andw $3, %dx |
||||
addw $0xcfc, %dx |
||||
inb %dx, %al |
||||
gs movb %al, OFFS_CL(%bp) |
||||
jmp clear_carry |
||||
|
||||
/*****************************************************************************/ |
||||
|
||||
pci_bios_read_cfg_word: |
||||
#ifdef PCI_BIOS_DEBUG |
||||
cs incl num_pci_bios_read_cfg_word |
||||
#endif |
||||
call pci_bios_select_register |
||||
gs movw OFFS_DI(%bp), %dx |
||||
andw $2, %dx |
||||
addw $0xcfc, %dx |
||||
inw %dx, %ax |
||||
gs movw %ax, OFFS_CX(%bp) |
||||
jmp clear_carry |
||||
|
||||
|
||||
/*****************************************************************************/ |
||||
|
||||
pci_bios_read_cfg_dword: |
||||
#ifdef PCI_BIOS_DEBUG |
||||
cs incl num_pci_bios_read_cfg_dword |
||||
#endif |
||||
call pci_bios_select_register |
||||
movw $0xcfc, %dx |
||||
inl %dx, %eax |
||||
gs movl %eax, OFFS_ECX(%bp) |
||||
jmp clear_carry |
||||
|
||||
/*****************************************************************************/ |
||||
|
||||
pci_bios_write_cfg_byte: |
||||
#ifdef PCI_BIOS_DEBUG |
||||
cs incl num_pci_bios_write_cfg_byte |
||||
#endif |
||||
call pci_bios_select_register |
||||
gs movw OFFS_DI(%bp), %dx |
||||
gs movb OFFS_CL(%bp), %al |
||||
andw $3, %dx |
||||
addw $0xcfc, %dx |
||||
outb %al, %dx |
||||
jmp clear_carry |
||||
|
||||
/*****************************************************************************/ |
||||
|
||||
pci_bios_write_cfg_word: |
||||
#ifdef PCI_BIOS_DEBUG |
||||
cs incl num_pci_bios_write_cfg_word |
||||
#endif |
||||
call pci_bios_select_register |
||||
gs movw OFFS_DI(%bp), %dx |
||||
gs movw OFFS_CX(%bp), %ax |
||||
andw $2, %dx |
||||
addw $0xcfc, %dx |
||||
outw %ax, %dx |
||||
jmp clear_carry |
||||
|
||||
/*****************************************************************************/ |
||||
|
||||
pci_bios_write_cfg_dword: |
||||
#ifdef PCI_BIOS_DEBUG |
||||
cs incl num_pci_bios_write_cfg_dword |
||||
#endif |
||||
call pci_bios_select_register |
||||
gs movl OFFS_ECX(%bp), %eax |
||||
movw $0xcfc, %dx |
||||
outl %eax, %dx |
||||
jmp clear_carry |
||||
|
||||
/*****************************************************************************/ |
||||
|
||||
pci_bios_get_irq_routing: |
||||
#ifdef PCI_BIOS_DEBUG |
||||
cs incl num_pci_bios_get_irq_routing |
||||
#endif |
||||
/* function not supported */ |
||||
movb $0x81, %ah |
||||
jmp set_carry |
||||
|
||||
/*****************************************************************************/ |
||||
|
||||
pci_bios_set_irq: |
||||
#ifdef PCI_BIOS_DEBUG |
||||
cs incl num_pci_bios_set_irq |
||||
#endif |
||||
/* function not supported */ |
||||
movb $0x81, %ah |
||||
jmp set_carry |
||||
|
||||
/*****************************************************************************/ |
||||
|
||||
unknown_function: |
||||
#ifdef PCI_BIOS_DEBUG |
||||
cs incl num_pci_bios_unknown_function |
||||
#endif |
||||
/* function not supported */ |
||||
movb $0x81, %ah |
||||
jmp set_carry |
||||
|
||||
/*****************************************************************************/ |
||||
|
||||
pci_bios_select_register: |
||||
gs movw OFFS_BX(%bp), %bx |
||||
gs movw OFFS_DI(%bp), %ax |
||||
/* destroys eax, dx */ |
||||
__pci_bios_select_register: |
||||
/* BX holds device id, AX holds register index */ |
||||
pushl %ebx |
||||
andl $0xfc, %eax |
||||
andl $0xffff, %ebx |
||||
shll $8, %ebx |
||||
orl %ebx, %eax |
||||
orl $0x80000000, %eax |
||||
movw $0xcf8, %dx |
||||
outl %eax, %dx |
||||
popl %ebx |
||||
ret |
||||
|
||||
|
||||
clear_carry: |
||||
gs movw OFFS_FLAGS(%bp), %ax |
||||
|
||||
/* clear carry -- function succeeded */ |
||||
andw $0xfffe, %ax |
||||
gs movw %ax, OFFS_FLAGS(%bp) |
||||
xorw %ax, %ax |
||||
gs movb %ah, OFFS_AH(%bp) |
||||
ret |
||||
|
||||
set_carry: |
||||
gs movb %ah, OFFS_AH(%bp) |
||||
gs movw OFFS_FLAGS(%bp), %ax |
||||
|
||||
/* return carry -- function not supported */ |
||||
orw $1, %ax |
||||
gs movw %ax, OFFS_FLAGS(%bp) |
||||
movw $-1, %ax |
||||
ret |
||||
|
||||
/*****************************************************************************/ |
||||
|
||||
.globl pci_last_bus
|
||||
pci_last_bus: |
||||
.byte 0
|
||||
|
||||
#ifdef PCI_BIOS_DEBUG |
||||
.globl num_pci_bios_present
|
||||
num_pci_bios_present: |
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_find_device
|
||||
num_pci_bios_find_device: |
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_find_class
|
||||
num_pci_bios_find_class: |
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_generate_special_cycle
|
||||
num_pci_bios_generate_special_cycle: |
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_read_cfg_byte
|
||||
num_pci_bios_read_cfg_byte: |
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_read_cfg_word
|
||||
num_pci_bios_read_cfg_word: |
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_read_cfg_dword
|
||||
num_pci_bios_read_cfg_dword: |
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_write_cfg_byte
|
||||
num_pci_bios_write_cfg_byte: |
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_write_cfg_word
|
||||
num_pci_bios_write_cfg_word: |
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_write_cfg_dword
|
||||
num_pci_bios_write_cfg_dword: |
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_get_irq_routing
|
||||
num_pci_bios_get_irq_routing: |
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_set_irq
|
||||
num_pci_bios_set_irq: |
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_unknown_function
|
||||
num_pci_bios_unknown_function: |
||||
.long 0
|
||||
#endif |
@ -1,179 +0,0 @@ |
||||
/*
|
||||
* (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 |
||||
*/ |
||||
|
||||
/*
|
||||
* Partly based on msbios.c from rolo 1.6: |
||||
*---------------------------------------------------------------------- |
||||
* (C) Copyright 2000 |
||||
* Sysgo Real-Time Solutions GmbH |
||||
* Klein-Winternheim, Germany |
||||
*---------------------------------------------------------------------- |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <pci.h> |
||||
#include <asm/realmode.h> |
||||
#include <asm/io.h> |
||||
#include "bios.h" |
||||
|
||||
DECLARE_GLOBAL_DATA_PTR; |
||||
|
||||
#define NUMVECTS 256 |
||||
|
||||
static int set_jmp_vector(int entry_point, void *target) |
||||
{ |
||||
if (entry_point & ~0xffff) |
||||
return -1; |
||||
|
||||
if (((u32)target - 0xf0000) & ~0xffff) |
||||
return -1; |
||||
|
||||
printf("set_jmp_vector: 0xf000:%04x -> %p\n", |
||||
entry_point, target); |
||||
|
||||
/* jmp opcode */ |
||||
writeb(0xea, 0xf0000 + entry_point); |
||||
|
||||
/* offset */ |
||||
writew(((u32)target-0xf0000), 0xf0000 + entry_point + 1); |
||||
|
||||
/* segment */ |
||||
writew(0xf000, 0xf0000 + entry_point + 3); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/* Install an interrupt vector */ |
||||
static void setvector(int vector, u16 segment, void *handler) |
||||
{ |
||||
u16 *ptr = (u16 *)(vector * 4); |
||||
ptr[0] = ((u32)handler - (segment << 4)) & 0xffff; |
||||
ptr[1] = segment; |
||||
|
||||
#if 0 |
||||
printf("setvector: int%02x -> %04x:%04x\n", |
||||
vector, ptr[1], ptr[0]); |
||||
#endif |
||||
} |
||||
|
||||
int bios_setup(void) |
||||
{ |
||||
/* The BIOS section is not relocated and still in the ROM. */ |
||||
ulong bios_start = (ulong)&__bios_start; |
||||
ulong bios_size = (ulong)&__bios_size; |
||||
|
||||
static int done; |
||||
int vector; |
||||
#ifdef CONFIG_PCI |
||||
struct pci_controller *pri_hose; |
||||
#endif |
||||
if (done) |
||||
return 0; |
||||
|
||||
done = 1; |
||||
|
||||
if (bios_size > 65536) { |
||||
printf("BIOS too large (%ld bytes, max is 65536)\n", |
||||
bios_size); |
||||
return -1; |
||||
} |
||||
|
||||
memcpy(BIOS_BASE, (void *)bios_start, bios_size); |
||||
|
||||
/* clear bda */ |
||||
memset(BIOS_DATA, 0, BIOS_DATA_SIZE); |
||||
|
||||
/* enter some values to the bda */ |
||||
writew(0x3f8, BIOS_DATA); /* com1 addr */ |
||||
writew(0x2f8, BIOS_DATA+2); /* com2 addr */ |
||||
writew(0x3e8, BIOS_DATA+4); /* com3 addr */ |
||||
writew(0x2e8, BIOS_DATA+6); /* com4 addr */ |
||||
writew(0x278, BIOS_DATA+8); /* lpt1 addr */ |
||||
/*
|
||||
* The kernel wants to read the base memory size |
||||
* from 40:13. Put a zero there to avoid an error message |
||||
*/ |
||||
writew(0, BIOS_DATA+0x13); /* base memory size */ |
||||
|
||||
|
||||
/* setup realmode interrupt vectors */ |
||||
for (vector = 0; vector < NUMVECTS; vector++) |
||||
setvector(vector, BIOS_CS, &rm_def_int); |
||||
|
||||
setvector(0x00, BIOS_CS, &rm_int00); |
||||
setvector(0x01, BIOS_CS, &rm_int01); |
||||
setvector(0x02, BIOS_CS, &rm_int02); |
||||
setvector(0x03, BIOS_CS, &rm_int03); |
||||
setvector(0x04, BIOS_CS, &rm_int04); |
||||
setvector(0x05, BIOS_CS, &rm_int05); |
||||
setvector(0x06, BIOS_CS, &rm_int06); |
||||
setvector(0x07, BIOS_CS, &rm_int07); |
||||
setvector(0x08, BIOS_CS, &rm_int08); |
||||
setvector(0x09, BIOS_CS, &rm_int09); |
||||
setvector(0x0a, BIOS_CS, &rm_int0a); |
||||
setvector(0x0b, BIOS_CS, &rm_int0b); |
||||
setvector(0x0c, BIOS_CS, &rm_int0c); |
||||
setvector(0x0d, BIOS_CS, &rm_int0d); |
||||
setvector(0x0e, BIOS_CS, &rm_int0e); |
||||
setvector(0x0f, BIOS_CS, &rm_int0f); |
||||
setvector(0x10, BIOS_CS, &rm_int10); |
||||
setvector(0x11, BIOS_CS, &rm_int11); |
||||
setvector(0x12, BIOS_CS, &rm_int12); |
||||
setvector(0x13, BIOS_CS, &rm_int13); |
||||
setvector(0x14, BIOS_CS, &rm_int14); |
||||
setvector(0x15, BIOS_CS, &rm_int15); |
||||
setvector(0x16, BIOS_CS, &rm_int16); |
||||
setvector(0x17, BIOS_CS, &rm_int17); |
||||
setvector(0x18, BIOS_CS, &rm_int18); |
||||
setvector(0x19, BIOS_CS, &rm_int19); |
||||
setvector(0x1a, BIOS_CS, &rm_int1a); |
||||
setvector(0x1b, BIOS_CS, &rm_int1b); |
||||
setvector(0x1c, BIOS_CS, &rm_int1c); |
||||
setvector(0x1d, BIOS_CS, &rm_int1d); |
||||
setvector(0x1e, BIOS_CS, &rm_int1e); |
||||
setvector(0x1f, BIOS_CS, &rm_int1f); |
||||
|
||||
set_jmp_vector(0xfff0, &realmode_reset); |
||||
set_jmp_vector(0xfe6e, &realmode_pci_bios_call_entry); |
||||
|
||||
/* fill in data area */ |
||||
RELOC_16_WORD(0xf000, ram_in_64kb_chunks) = gd->ram_size >> 16; |
||||
RELOC_16_WORD(0xf000, bios_equipment) = 0; /* FixMe */ |
||||
|
||||
/* If we assume only one PCI hose, this PCI hose
|
||||
* will own PCI bus #0, and the last PCI bus of |
||||
* that PCI hose will be the last PCI bus in the |
||||
* system. |
||||
* (This, ofcause break on multi hose systems, |
||||
* but our PCI BIOS only support one hose anyway) |
||||
*/ |
||||
#ifdef CONFIG_PCI |
||||
pri_hose = pci_bus_to_hose(0); |
||||
if (NULL != pri_hose) { |
||||
/* fill in last pci bus number for use by the realmode
|
||||
* PCI BIOS */ |
||||
RELOC_16_BYTE(0xf000, pci_last_bus) = pri_hose->last_busno; |
||||
} |
||||
#endif |
||||
return 0; |
||||
} |
@ -1,93 +0,0 @@ |
||||
/*
|
||||
* (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 |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <asm/io.h> |
||||
#include <asm/ptrace.h> |
||||
#include <asm/realmode.h> |
||||
|
||||
#define REALMODE_MAILBOX ((char *)0xe00) |
||||
|
||||
int realmode_setup(void) |
||||
{ |
||||
/* The realmode section is not relocated and still in the ROM. */ |
||||
ulong realmode_start = (ulong)&__realmode_start; |
||||
ulong realmode_size = (ulong)&__realmode_size; |
||||
|
||||
/* copy the realmode switch code */ |
||||
if (realmode_size > (REALMODE_MAILBOX - (char *)REALMODE_BASE)) { |
||||
printf("realmode switch too large (%ld bytes, max is %d)\n", |
||||
realmode_size, |
||||
(int)(REALMODE_MAILBOX - (char *)REALMODE_BASE)); |
||||
return -1; |
||||
} |
||||
|
||||
memcpy((char *)REALMODE_BASE, (void *)realmode_start, realmode_size); |
||||
asm("wbinvd\n"); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out) |
||||
{ |
||||
|
||||
/* setup out thin bios emulation */ |
||||
if (bios_setup()) |
||||
return -1; |
||||
|
||||
if (realmode_setup()) |
||||
return -1; |
||||
|
||||
in->eip = off; |
||||
in->xcs = seg; |
||||
if ((in->esp & 0xffff) < 4) |
||||
printf("Warning: entering realmode with sp < 4 will fail\n"); |
||||
|
||||
memcpy(REALMODE_MAILBOX, in, sizeof(struct pt_regs)); |
||||
asm("wbinvd\n"); |
||||
|
||||
__asm__ volatile ( |
||||
"lcall $0x20,%0\n" : : "i" (&realmode_enter)); |
||||
|
||||
asm("wbinvd\n"); |
||||
memcpy(out, REALMODE_MAILBOX, sizeof(struct pt_regs)); |
||||
|
||||
return out->eax; |
||||
} |
||||
|
||||
/*
|
||||
* This code is supposed to access a realmode interrupt |
||||
* it does currently not work for me |
||||
*/ |
||||
int enter_realmode_int(u8 lvl, struct pt_regs *in, struct pt_regs *out) |
||||
{ |
||||
/* place two instructions at 0x700 */ |
||||
writeb(0xcd, 0x700); /* int $lvl */ |
||||
writeb(lvl, 0x701); |
||||
writeb(0xcb, 0x702); /* lret */ |
||||
asm("wbinvd\n"); |
||||
|
||||
enter_realmode(0x00, 0x700, in, out); |
||||
|
||||
return out->eflags & 0x00000001; |
||||
} |
@ -1,232 +0,0 @@ |
||||
/* |
||||
* (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 |
||||
*/ |
||||
|
||||
/* 32bit -> 16bit -> 32bit mode switch code */ |
||||
|
||||
/* |
||||
* Stack frame at 0xe00 |
||||
* e00 ebx;
|
||||
* e04 ecx;
|
||||
* e08 edx;
|
||||
* e0c esi;
|
||||
* e10 edi;
|
||||
* e14 ebp;
|
||||
* e18 eax;
|
||||
* e1c ds;
|
||||
* e20 es;
|
||||
* e24 fs;
|
||||
* e28 gs;
|
||||
* e2c orig_eax;
|
||||
* e30 eip;
|
||||
* e34 cs;
|
||||
* e38 eflags;
|
||||
* e3c esp;
|
||||
* e40 ss;
|
||||
*/ |
||||
|
||||
#define a32 .byte 0x67; /* address size prefix 32 */
|
||||
#define o32 .byte 0x66; /* operand size prefix 32 */
|
||||
|
||||
.section .realmode, "ax" |
||||
.code16 |
||||
|
||||
/* 16bit protected mode code here */ |
||||
.globl realmode_enter
|
||||
realmode_enter: |
||||
o32 pusha |
||||
o32 pushf |
||||
cli |
||||
sidt saved_idt |
||||
sgdt saved_gdt |
||||
movl %esp, %eax |
||||
movl %eax, saved_protected_mode_esp |
||||
|
||||
movl $0x10, %eax |
||||
movl %eax, %esp |
||||
movw $0x28, %ax |
||||
movw %ax, %ds |
||||
movw %ax, %es |
||||
movw %ax, %fs |
||||
movw %ax, %gs |
||||
|
||||
lidt realmode_idt_ptr |
||||
/* Go back into real mode by clearing PE to 0 */ |
||||
movl %cr0, %eax |
||||
andl $0x7ffffffe, %eax |
||||
movl %eax, %cr0 |
||||
|
||||
/* switch to real mode */ |
||||
ljmp $0x0,$do_realmode |
||||
|
||||
do_realmode: |
||||
/* realmode code from here */ |
||||
movw %cs,%ax |
||||
movw %ax,%ds |
||||
movw %ax,%es |
||||
movw %ax,%fs |
||||
movw %ax,%gs |
||||
|
||||
/* create a temporary stack */ |
||||
movw $0xc0, %ax |
||||
movw %ax, %ss |
||||
movw $0x200, %ax |
||||
movw %ax, %sp |
||||
|
||||
popl %ebx |
||||
popl %ecx |
||||
popl %edx |
||||
popl %esi |
||||
popl %edi |
||||
popl %ebp |
||||
popl %eax |
||||
movl %eax, temp_eax |
||||
popl %eax |
||||
movw %ax, %ds |
||||
popl %eax |
||||
movw %ax, %es |
||||
popl %eax |
||||
movw %ax, %fs |
||||
popl %eax |
||||
movw %ax, %gs |
||||
popl %eax /* orig_eax */ |
||||
popl %eax |
||||
cs movw %ax, temp_ip |
||||
popl %eax |
||||
cs movw %ax, temp_cs |
||||
o32 popf |
||||
popl %eax |
||||
popw %ss |
||||
movl %eax, %esp |
||||
cs movl temp_eax, %eax |
||||
|
||||
/* self-modifying code, better flush the cache */ |
||||
wbinvd |
||||
|
||||
.byte 0x9a /* lcall */ |
||||
temp_ip: |
||||
.word 0 /* new ip */ |
||||
temp_cs: |
||||
.word 0 /* new cs */ |
||||
|
||||
realmode_ret: |
||||
/* save eax, esp and ss */ |
||||
cs movl %eax, saved_eax |
||||
movl %esp, %eax |
||||
cs movl %eax, saved_esp |
||||
movw %ss, %ax |
||||
cs movw %ax, saved_ss |
||||
|
||||
/* |
||||
* restore the stack, note that we set sp to 0x244;
|
||||
* pt_regs is 0x44 bytes long and we push the structure |
||||
* backwards on to the stack, bottom first |
||||
*/ |
||||
movw $0xc0, %ax |
||||
movw %ax, %ss |
||||
movw $0x244, %ax |
||||
movw %ax, %sp |
||||
|
||||
xorl %eax,%eax |
||||
cs movw saved_ss, %ax |
||||
pushl %eax |
||||
cs movl saved_esp, %eax |
||||
pushl %eax |
||||
o32 pushf |
||||
xorl %eax,%eax |
||||
cs movw temp_cs, %ax |
||||
pushl %eax |
||||
cs movw temp_ip, %ax |
||||
pushl %eax |
||||
pushl $0 |
||||
movw %gs, %ax |
||||
pushl %eax |
||||
movw %fs, %ax |
||||
pushl %eax |
||||
movw %es, %ax |
||||
pushl %eax |
||||
movw %ds, %ax |
||||
pushl %eax |
||||
movl saved_eax, %eax |
||||
pushl %eax |
||||
pushl %ebp |
||||
pushl %edi |
||||
pushl %esi |
||||
pushl %edx |
||||
pushl %ecx |
||||
pushl %ebx |
||||
|
||||
o32 cs lidt saved_idt |
||||
o32 cs lgdt saved_gdt |
||||
|
||||
/* Go back into protected mode reset PE to 1 */ |
||||
movl %cr0, %eax |
||||
orl $1,%eax |
||||
movl %eax, %cr0 |
||||
|
||||
/* flush prefetch queue */ |
||||
jmp next_line |
||||
next_line: |
||||
movw $return_ptr, %ax |
||||
movw %ax,%bp |
||||
o32 cs ljmp *(%bp) |
||||
|
||||
.code32 |
||||
protected_mode: |
||||
/* Reload segment registers */ |
||||
movl $0x18, %eax |
||||
movw %ax, %fs |
||||
movw %ax, %ds |
||||
movw %ax, %gs |
||||
movw %ax, %es |
||||
movw %ax, %ss |
||||
movl saved_protected_mode_esp, %eax |
||||
movl %eax, %esp |
||||
popf |
||||
popa |
||||
ret |
||||
|
||||
temp_eax: |
||||
.long 0
|
||||
|
||||
saved_ss: |
||||
.word 0
|
||||
saved_esp: |
||||
.long 0
|
||||
saved_eax: |
||||
.long 0
|
||||
|
||||
realmode_idt_ptr: |
||||
.word 0x400
|
||||
.word 0x0, 0x0 |
||||
|
||||
saved_gdt: |
||||
.word 0, 0, 0, 0 |
||||
saved_idt: |
||||
.word 0, 0, 0, 0 |
||||
|
||||
saved_protected_mode_esp: |
||||
.long 0
|
||||
|
||||
return_ptr: |
||||
.long protected_mode
|
||||
.word 0x10
|
@ -1,196 +0,0 @@ |
||||
/*
|
||||
* (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 |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <pci.h> |
||||
#include <malloc.h> |
||||
#include <asm/ptrace.h> |
||||
#include <asm/realmode.h> |
||||
#include <asm/io.h> |
||||
#include <asm/pci.h> |
||||
#include "bios.h" |
||||
|
||||
#undef PCI_BIOS_DEBUG |
||||
#undef VGA_BIOS_DEBUG |
||||
|
||||
#ifdef VGA_BIOS_DEBUG |
||||
#define PRINTF(fmt, args...) printf(fmt, ##args) |
||||
#else |
||||
#define PRINTF(fmt, args...) |
||||
#endif |
||||
|
||||
#define PCI_CLASS_VIDEO 3 |
||||
#define PCI_CLASS_VIDEO_STD 0 |
||||
#define PCI_CLASS_VIDEO_PROG_IF_VGA 0 |
||||
|
||||
DEFINE_PCI_DEVICE_TABLE(supported) = { |
||||
{PCI_VIDEO_VENDOR_ID, PCI_VIDEO_DEVICE_ID}, |
||||
{} |
||||
}; |
||||
|
||||
static u32 probe_pci_video(void) |
||||
{ |
||||
struct pci_controller *hose; |
||||
pci_dev_t devbusfn = pci_find_devices(supported, 0); |
||||
|
||||
if ((devbusfn != -1)) { |
||||
u32 old; |
||||
u32 addr; |
||||
|
||||
/* PCI video device detected */ |
||||
printf("Found PCI VGA device at %02x.%02x.%x\n", |
||||
PCI_BUS(devbusfn), |
||||
PCI_DEV(devbusfn), |
||||
PCI_FUNC(devbusfn)); |
||||
|
||||
/* Enable I/O decoding as well, PCI viudeo boards
|
||||
* support I/O accesses, but they provide no |
||||
* bar register for this since the ports are fixed. |
||||
*/ |
||||
pci_write_config_word(devbusfn, |
||||
PCI_COMMAND, |
||||
PCI_COMMAND_MEMORY | |
||||
PCI_COMMAND_IO | |
||||
PCI_COMMAND_MASTER); |
||||
|
||||
/* Test the ROM decoder, do the device support a rom? */ |
||||
pci_read_config_dword(devbusfn, PCI_ROM_ADDRESS, &old); |
||||
pci_write_config_dword(devbusfn, PCI_ROM_ADDRESS, |
||||
(u32)PCI_ROM_ADDRESS_MASK); |
||||
pci_read_config_dword(devbusfn, PCI_ROM_ADDRESS, &addr); |
||||
pci_write_config_dword(devbusfn, PCI_ROM_ADDRESS, old); |
||||
|
||||
if (!addr) { |
||||
printf("PCI VGA have no ROM?\n"); |
||||
return 0; |
||||
} |
||||
|
||||
/* device have a rom */ |
||||
if (pci_shadow_rom(devbusfn, (void *)0xc0000)) { |
||||
printf("Shadowing of PCI VGA BIOS failed\n"); |
||||
return 0; |
||||
} |
||||
|
||||
/* Now enable lagacy VGA port access */ |
||||
hose = pci_bus_to_hose(PCI_BUS(devbusfn)); |
||||
if (pci_enable_legacy_video_ports(hose)) { |
||||
printf("PCI VGA enable failed\n"); |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
/* return the pci device info, that we'll need later */ |
||||
return PCI_BUS(devbusfn) << 8 | |
||||
PCI_DEV(devbusfn) << 3 | (PCI_FUNC(devbusfn) & 7); |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int probe_isa_video(void) |
||||
{ |
||||
u32 ptr; |
||||
char *buf; |
||||
|
||||
ptr = isa_map_rom(0xc0000, 0x8000); |
||||
|
||||
if (!ptr) |
||||
return -1; |
||||
|
||||
buf = malloc(0x8000); |
||||
if (!buf) { |
||||
isa_unmap_rom(ptr); |
||||
return -1; |
||||
} |
||||
|
||||
if (readw(ptr) != 0xaa55) { |
||||
free(buf); |
||||
isa_unmap_rom(ptr); |
||||
return -1; |
||||
} |
||||
|
||||
/* shadow the rom */ |
||||
memcpy(buf, (void *)ptr, 0x8000); |
||||
isa_unmap_rom(ptr); |
||||
memcpy((void *)0xc0000, buf, 0x8000); |
||||
|
||||
free(buf); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int video_bios_init(void) |
||||
{ |
||||
struct pt_regs regs; |
||||
int size; |
||||
int i; |
||||
u8 sum; |
||||
|
||||
/* clear the video bios area in case we warmbooted */ |
||||
memset((void *)0xc0000, 0, 0x8000); |
||||
memset(®s, 0, sizeof(struct pt_regs)); |
||||
|
||||
if (probe_isa_video()) |
||||
/* No ISA board found, try the PCI bus */ |
||||
regs.eax = probe_pci_video(); |
||||
|
||||
/* Did we succeed in mapping any video bios */ |
||||
if (readw(0xc0000) == 0xaa55) { |
||||
PRINTF("Found video bios signature\n"); |
||||
size = readb(0xc0002) * 512; |
||||
PRINTF("size %d\n", size); |
||||
sum = 0; |
||||
|
||||
for (i = 0; i < size; i++) |
||||
sum += readb(0xc0000 + i); |
||||
|
||||
PRINTF("Checksum is %sOK\n", sum ? "NOT " : ""); |
||||
|
||||
if (sum) |
||||
return 1; |
||||
|
||||
/*
|
||||
* Some video bioses (ATI Mach64) seem to think that |
||||
* the original int 10 handler is always at |
||||
* 0xf000:0xf065 , place an iret instruction there |
||||
*/ |
||||
writeb(0xcf, 0xff065); |
||||
|
||||
regs.esp = 0x8000; |
||||
regs.xss = 0x2000; |
||||
enter_realmode(0xc000, 3, ®s, ®s); |
||||
|
||||
PRINTF("INT 0x10 vector after: %04x:%04x\n", |
||||
readw(0x42), readw(0x40)); |
||||
PRINTF("BIOS returned %scarry\n", |
||||
regs.eflags & 0x00000001 ? "" : "NOT "); |
||||
#ifdef PCI_BIOS_DEBUG |
||||
print_bios_bios_stat(); |
||||
#endif |
||||
return regs.eflags & 0x00000001; |
||||
|
||||
} |
||||
|
||||
return 1; |
||||
|
||||
} |
Loading…
Reference in new issue