summaryrefslogtreecommitdiff
path: root/lib_i386
diff options
context:
space:
mode:
Diffstat (limited to 'lib_i386')
-rw-r--r--lib_i386/Makefile6
-rw-r--r--lib_i386/bios.S135
-rw-r--r--lib_i386/bios.h94
-rw-r--r--lib_i386/bios_pci.S411
-rw-r--r--lib_i386/bios_setup.c60
-rw-r--r--lib_i386/board.c34
-rw-r--r--lib_i386/ic/ali512x.c442
-rw-r--r--lib_i386/ic/sc520.c348
-rw-r--r--lib_i386/ic/sc520_asm.S530
-rw-r--r--lib_i386/pci.c156
-rw-r--r--lib_i386/realmode.c44
-rw-r--r--lib_i386/realmode_switch.S1
-rw-r--r--lib_i386/video.c238
-rw-r--r--lib_i386/video_bios.c221
-rw-r--r--lib_i386/zimage.c4
15 files changed, 1312 insertions, 1412 deletions
diff --git a/lib_i386/Makefile b/lib_i386/Makefile
index 34994e5446b..47c5d2cd948 100644
--- a/lib_i386/Makefile
+++ b/lib_i386/Makefile
@@ -25,11 +25,11 @@ include $(TOPDIR)/config.mk
LIB = lib$(ARCH).a
-AOBJS = bios.o realmode_switch.o ic/sc520_asm.o
+AOBJS = bios.o bios_pci.o realmode_switch.o
COBJS = board.o bios_setup.o i386_linux.o zimage.o realmode.o \
- pci_type1.o ic/sc520.o ic/ali512x.o
-
+ pci_type1.o pci.o video_bios.o video.o
+
OBJS = $(AOBJS) $(COBJS)
$(LIB): .depend $(OBJS)
diff --git a/lib_i386/bios.S b/lib_i386/bios.S
index 2f5ea8cda92..ce6e94cae1d 100644
--- a/lib_i386/bios.S
+++ b/lib_i386/bios.S
@@ -30,6 +30,8 @@
*----------------------------------------------------------------------
*/
+#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
@@ -40,29 +42,13 @@
* 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
-
+ /* a call to f000:0 should warmboot */
+ jmp realmode_reset
+
.globl rm_int00
rm_int00:
pushw $0
@@ -202,30 +188,23 @@ rm_def_int:
* 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 */
+ 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 */
@@ -234,6 +213,9 @@ Lint_10h: /* VGA BIOS services */
Lint_11h:
call bios_11h
jmp Lout
+Lint_12h:
+ call bios_12h
+ jmp Lout
Lint_13h: /* BIOS disk services */
call bios_13h
jmp Lout
@@ -243,6 +225,9 @@ Lint_15h: /* Misc. BIOS services */
Lint_16h: /* keyboard services */
call bios_16h
jmp Lout
+Lint_1ah: /* PCI bios */
+ call bios_1ah
+ jmp Lout
Lout:
cmpw $0, %ax
je Lhandeled
@@ -256,16 +241,7 @@ Lout:
* 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 */
+ RESTORE_CALLERS_STACK
addw $2,%sp /* dump vector number */
iret /* return from interrupt */
@@ -309,7 +285,7 @@ gs movw $0x10, OFFS_BX(%bp) /* indicate CGA/MDA/HGA */
*/
bios_11h:
- movw bios_equipment, %ax
+cs movw bios_equipment, %ax
gs movw %ax, OFFS_AX(%bp)
xorw %ax, %ax
ret
@@ -317,6 +293,30 @@ gs movw %ax, OFFS_AX(%bp)
/*
************************************************************
+ * 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
************************************************************
*/
@@ -372,27 +372,28 @@ gs movw %ax, OFFS_FLAGS(%bp)
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 */
+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)
- xorw %ax, %ax
-gs movw %ax, OFFS_BX(%bp) /* set BX and DX to 0*/
-gs movw %ax, OFFS_DX(%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
-Lmore_than_16mb:
+e801_more_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_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 - 256 */
+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
@@ -402,11 +403,15 @@ gs movw %ax, OFFS_FLAGS(%bp)
ret
Lfunc_88h:
- movw ram_in_64kb_chunks, %ax
- subw $16, %ax
+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
-
-gs movw %ax, OFFS_AX(%bp) /* return number of kilobytes in 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 */
@@ -432,6 +437,22 @@ 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:
diff --git a/lib_i386/bios.h b/lib_i386/bios.h
new file mode 100644
index 00000000000..876fe31b260
--- /dev/null
+++ b/lib_i386/bios.h
@@ -0,0 +1,94 @@
+/*
+ * (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 _BIOS_H_
+#define _BIOS_H_
+
+#define OFFS_ES 0 /* 16bit */
+#define OFFS_GS 2 /* 16bit */
+#define OFFS_DS 4 /* 16bit */
+#define OFFS_EDI 6 /* 32bit */
+#define OFFS_DI 6 /* low 16 bits of EDI */
+#define OFFS_ESI 10 /* 32bit */
+#define OFFS_SI 10 /* low 16 bits of ESI */
+#define OFFS_EBP 14 /* 32bit */
+#define OFFS_BP 14 /* low 16 bits of EBP */
+#define OFFS_ESP 18 /* 32bit */
+#define OFFS_SP 18 /* low 16 bits of ESP */
+#define OFFS_EBX 22 /* 32bit */
+#define OFFS_BX 22 /* low 16 bits of EBX */
+#define OFFS_BL 22 /* low 8 bits of BX */
+#define OFFS_BH 23 /* high 8 bits of BX */
+#define OFFS_EDX 26 /* 32bit */
+#define OFFS_DX 26 /* low 16 bits of EBX */
+#define OFFS_DL 26 /* low 8 bits of BX */
+#define OFFS_DH 27 /* high 8 bits of BX */
+#define OFFS_ECX 30 /* 32bit */
+#define OFFS_CX 30 /* low 16 bits of EBX */
+#define OFFS_CL 30 /* low 8 bits of BX */
+#define OFFS_CH 31 /* high 8 bits of BX */
+#define OFFS_EAX 34 /* 32bit */
+#define OFFS_AX 34 /* low 16 bits of EBX */
+#define OFFS_AL 34 /* low 8 bits of BX */
+#define OFFS_AH 35 /* high 8 bits of BX */
+#define OFFS_VECTOR 38 /* 16bit */
+#define OFFS_IP 40 /* 16bit */
+#define OFFS_CS 42 /* 16bit */
+#define OFFS_FLAGS 44 /* 16bit */
+
+#define SEGMENT 0x40
+#define STACK 0x800 /* stack at 0x40:0x800 -> 0x800 */
+
+/* save general registers */
+/* save some segments */
+/* save callers stack segment .. */
+/* ... in gs */
+ /* setup my segments */
+ /* setup BIOS stackpointer */
+
+#define MAKE_BIOS_STACK \
+ pushal ; \
+ pushw %ds ; \
+ pushw %gs ; \
+ pushw %es ; \
+ pushw %ss ; \
+ popw %gs ; \
+ movw $SEGMENT,%ax ; \
+ movw %ax,%ds ; \
+ movw %ax,%es ; \
+ movw %ax,%ss ; \
+ movw %sp,%bp ; \
+ movw $STACK,%sp
+
+#define RESTORE_CALLERS_STACK \
+ pushw %gs ; /* restore callers stack segment */ \
+ popw %ss ; \
+ movw %bp,%sp ; /* restore stackpointer */ \
+ \
+ popw %es ; /* restore segment selectors */ \
+ popw %gs ; \
+ popw %ds ; \
+ \
+ popal /* restore GP registers */
+
+#endif
diff --git a/lib_i386/bios_pci.S b/lib_i386/bios_pci.S
new file mode 100644
index 00000000000..e53791a1538
--- /dev/null
+++ b/lib_i386/bios_pci.S
@@ -0,0 +1,411 @@
+/*
+ * (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
+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)
+ movb $0x01, %al
+gs movb %al, OFFS_AL(%bp) /* We support cfg type 1 */
+ movw $0x0210, %ax /* version 2.10 */
+gs movw %ax, OFFS_BX(%bp)
+cs movb pci_last_bus, %al /* last bus number */
+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
+ xorw %bx, %bx /* start at bus 0 dev 0 function 0 */
+pfd_loop:
+ xorw %ax, %ax /* dword 0 is vendor/device */
+ call __pci_bios_select_register
+ movw $0xcfc, %dx
+ inl %dx, %eax
+ cmpl %edi, %eax /* our device ? */
+ 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:
+ incw %bx /* next function, overflows in to
+ * device number, then bus number */
+ jmp pfd_check_bus
+
+pfd_not_multi_function:
+ andw $0xfff8, %bx /* remove function bits */
+ addw $0x0008, %bx /* next device, overflows in to bus number */
+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:
+ movb $0x86, %ah /* device not found */
+ 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
+ andl $0x00ffffff, %edi /* edi now holds class-code in lower 24 bits */
+gs movw OFFS_SI(%bp), %si
+ xorw %bx, %bx /* start at bus 0 dev 0 function 0 */
+pfc_loop:
+ movw $8, %ax /* dword 8 is class-code high 24bits */
+ call __pci_bios_select_register
+ movw $0xcfc, %dx
+ inl %dx, %eax
+ shrl $8, %eax
+ andl $0x00ffffff, %eax
+ cmpl %edi, %eax /* our device ? */
+ 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:
+ incw %bx /* next function, overflows in to
+ * device number, then bus number */
+ jmp pfc_check_bus
+
+pfc_not_multi_function:
+ andw $0xfff8, %bx /* remove function bits */
+ addw $0x0008, %bx /* next device, overflows in to bus number */
+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:
+ movb $0x86, %ah /* device not found */
+ jmp set_carry
+
+/*****************************************************************************/
+
+pci_bios_generate_special_cycle:
+#ifdef PCI_BIOS_DEBUG
+cs incl num_pci_bios_generate_special_cycle
+#endif
+ movb $0x81, %ah /* function not supported */
+ 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
+ movb $0x81, %ah /* function not supported */
+ jmp set_carry
+
+/*****************************************************************************/
+
+pci_bios_set_irq:
+#ifdef PCI_BIOS_DEBUG
+cs incl num_pci_bios_set_irq
+#endif
+ movb $0x81, %ah /* function not supported */
+ jmp set_carry
+
+/*****************************************************************************/
+
+unknown_function:
+#ifdef PCI_BIOS_DEBUG
+cs incl num_pci_bios_unknown_function
+#endif
+ movb $0x81, %ah /* function not supported */
+ 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
+ andw $0xfffe, %ax /* clear carry -- function succeeded */
+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
+ orw $1, %ax /* return carry -- function not supported */
+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
diff --git a/lib_i386/bios_setup.c b/lib_i386/bios_setup.c
index 94319afc589..3da7858164d 100644
--- a/lib_i386/bios_setup.c
+++ b/lib_i386/bios_setup.c
@@ -32,6 +32,7 @@
*/
#include <common.h>
+#include <pci.h>
#include <asm/realmode.h>
#include <asm/io.h>
@@ -42,8 +43,13 @@
#define BIOS_BASE ((char*)0xf0000)
#define BIOS_CS 0xf000
+/* these are defined in a 16bit segment and needs
+ * to be accessed with the RELOC_16_xxxx() macros below
+ */
extern u16 ram_in_64kb_chunks;
extern u16 bios_equipment;
+extern u8 pci_last_bus;
+
extern void *rm_int00;
extern void *rm_int01;
extern void *rm_int02;
@@ -78,6 +84,34 @@ extern void *rm_int1e;
extern void *rm_int1f;
extern void *rm_def_int;
+extern void *realmode_reset;
+extern void *realmode_pci_bios_call_entry;
+
+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
@@ -96,11 +130,16 @@ static void setvector(int vector, u16 segment, void *handler)
#endif
}
+#define RELOC_16_LONG(seg, off) *(u32*)(seg << 4 | (u32)&off)
+#define RELOC_16_WORD(seg, off) *(u16*)(seg << 4 | (u32)&off)
+#define RELOC_16_BYTE(seg, off) *(u8*)(seg << 4 | (u32)&off)
+
int bios_setup(void)
{
DECLARE_GLOBAL_DATA_PTR;
static int done=0;
int vector;
+ struct pci_controller *pri_hose;
if (done) {
return 0;
@@ -169,9 +208,26 @@ int bios_setup(void)
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 */
- ram_in_64kb_chunks = gd->ram_size >> 16;
- bios_equipment = 0; /* FixMe */
+ 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)
+ */
+ 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;
+ }
return 0;
}
diff --git a/lib_i386/board.c b/lib_i386/board.c
index 193860a87a4..85d7d7fb8c6 100644
--- a/lib_i386/board.c
+++ b/lib_i386/board.c
@@ -37,6 +37,7 @@
#include <syscall.h>
#include <net.h>
#include <ide.h>
+#include <asm/u-boot-i386.h>
extern long _i386boot_start;
extern long _i386boot_end;
@@ -82,21 +83,14 @@ static int mem_malloc_init(void)
{
DECLARE_GLOBAL_DATA_PTR;
-#if 1
/* start malloc area right after the stack */
mem_malloc_start = i386boot_bss_start +
i386boot_bss_size + CFG_STACK_SIZE;
mem_malloc_start = (mem_malloc_start+3)&~3;
-#else
- mem_malloc_start = 0x400000;
-#endif
-#if 1
+
/* Use all available RAM for malloc() */
mem_malloc_end = gd->ram_size;
-#else
- /* Use only CONFIG_MALLOC_SIZE bytes of RAM for malloc() */
- mem_malloc_end = mem_malloc_start + CONFIG_MALLOC_SIZE;
-#endif
+
mem_malloc_brk = mem_malloc_start;
return 0;
@@ -149,10 +143,10 @@ static int init_baudrate (void)
{
DECLARE_GLOBAL_DATA_PTR;
- uchar tmp[64]; /* long enough for environment variables */
- int i = getenv_r ("baudrate", tmp, sizeof (tmp));
+ char tmp[64]; /* long enough for environment variables */
+ int i = getenv_r("baudrate", tmp, 64);
- gd->baudrate = (i > 0)
+ gd->baudrate = (i != 0)
? (int) simple_strtoul (tmp, NULL, 10)
: CONFIG_BAUDRATE;
@@ -237,6 +231,7 @@ init_fnc_t *init_sequence[] = {
mem_malloc_init, /* dependant on dram_init */
interrupt_init, /* set up exceptions */
timer_init,
+ serial_init,
env_init, /* initialize environment */
init_baudrate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
@@ -267,6 +262,7 @@ void start_i386boot (void)
memset (gd->bd, 0, sizeof (bd_t));
show_boot_progress(0x22);
+ gd->baudrate = CONFIG_BAUDRATE;
for (init_fnc_ptr = init_sequence, i=0; *init_fnc_ptr; ++init_fnc_ptr, i++) {
show_boot_progress(0xa130|i);
@@ -323,7 +319,8 @@ void start_i386boot (void)
/* allocate syscalls table (console_init_r will fill it in */
syscall_tbl = (void **) malloc (NR_SYSCALLS * sizeof (void *));
-
+ memset(syscall_tbl, 0, NR_SYSCALLS * sizeof (void *));
+
/* Initialize the console (after the relocation and devices init) */
console_init_r();
syscalls_init();
@@ -355,7 +352,7 @@ void start_i386boot (void)
#endif
/* enable exceptions */
- enable_interrupts ();
+ enable_interrupts();
show_boot_progress(0x28);
/* Must happen after interrupts are initialized since
@@ -369,7 +366,7 @@ void start_i386boot (void)
status_led_set (STATUS_LED_BOOT, STATUS_LED_BLINKING);
#endif
- udelay (20);
+ udelay(20);
set_timer (0);
@@ -399,7 +396,7 @@ void start_i386boot (void)
#if (CONFIG_COMMANDS & CFG_CMD_DOC)
WATCHDOG_RESET();
- puts ("DOC: ");
+ puts("DOC: ");
doc_init();
#endif
@@ -428,12 +425,13 @@ void start_i386boot (void)
board_poweroff();
}
#endif
-
+
+
show_boot_progress(0x29);
/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
- main_loop ();
+ main_loop();
}
/* NOTREACHED - no way out of command loop except booting */
diff --git a/lib_i386/ic/ali512x.c b/lib_i386/ic/ali512x.c
deleted file mode 100644
index 4537095dbef..00000000000
--- a/lib_i386/ic/ali512x.c
+++ /dev/null
@@ -1,442 +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 sc520cdp.c from rolo 1.6:
- *----------------------------------------------------------------------
- * (C) Copyright 2000
- * Sysgo Real-Time Solutions GmbH
- * Klein-Winternheim, Germany
- *----------------------------------------------------------------------
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/ic/ali512x.h>
-
-
-/* ALI M5123 Logical device numbers:
- * 0 FDC
- * 1 unused?
- * 2 unused?
- * 3 lpt
- * 4 UART1
- * 5 UART2
- * 6 RTC
- * 7 mouse/kbd
- * 8 CIO
- */
-
-/*
- ************************************************************
- * Some access primitives for the ALi chip: *
- ************************************************************
- */
-
-static void ali_write(u8 index, u8 value)
-{
- /* write an arbirary register */
- outb(index, ALI_INDEX);
- outb(value, ALI_DATA);
-}
-
-static int ali_read(u8 index)
-{
- outb(index, ALI_INDEX);
- return inb(ALI_DATA);
-}
-
-#define ALI_OPEN() \
- outb(0x51, ALI_DATA); \
- outb(0x23, ALI_DATA)
-
-
-#define ALI_CLOSE() \
- outb(0xbb, ALI_DATA)
-
-/* Select a logical device */
-#define ALI_SELDEV(dev) \
- ali_write(0x07, dev)
-
-
-void ali512x_init(void)
-{
- ALI_OPEN();
-
- ali_write(0x02, 0x01); /* soft reset */
- ali_write(0x03, 0x03); /* disable access to CIOs */
- ali_write(0x22, 0x00); /* disable direct powerdown */
- ali_write(0x23, 0x00); /* disable auto powerdown */
- ali_write(0x24, 0x00); /* IR 8 is active hi, pin26 is PDIR */
-
- ALI_CLOSE();
-}
-
-void ali512x_set_fdc(int enabled, u16 io, u8 irq, u8 dma_channel)
-{
- ALI_OPEN();
- ALI_SELDEV(0);
-
- ali_write(0x30, enabled?1:0);
- if (enabled) {
- ali_write(0x60, io >> 8);
- ali_write(0x61, io & 0xff);
- ali_write(0x70, irq);
- ali_write(0x74, dma_channel);
-
- /* AT mode, no drive swap */
- ali_write(0xf0, 0x08);
- ali_write(0xf1, 0x00);
- ali_write(0xf2, 0xff);
- ali_write(0xf4, 0x00);
- }
- ALI_CLOSE();
-}
-
-
-void ali512x_set_pp(int enabled, u16 io, u8 irq, u8 dma_channel)
-{
- ALI_OPEN();
- ALI_SELDEV(3);
-
- ali_write(0x30, enabled?1:0);
- if (enabled) {
- ali_write(0x60, io >> 8);
- ali_write(0x61, io & 0xff);
- ali_write(0x70, irq);
- ali_write(0x74, dma_channel);
-
- /* mode: EPP 1.9, ECP FIFO threshold = 7, IRQ active low */
- ali_write(0xf0, 0xbc);
- /* 12 MHz, Burst DMA in ECP */
- ali_write(0xf1, 0x05);
- }
- ALI_CLOSE();
-
-}
-
-void ali512x_set_uart(int enabled, int index, u16 io, u8 irq)
-{
- ALI_OPEN();
- ALI_SELDEV(index?5:4);
-
- ali_write(0x30, enabled?1:0);
- if (enabled) {
- ali_write(0x60, io >> 8);
- ali_write(0x61, io & 0xff);
- ali_write(0x70, irq);
-
- ali_write(0xf0, 0x00);
- ali_write(0xf1, 0x00);
-
- /* huh? write 0xf2 twice - a typo in rolo
- * or some secret ali errata? Who knows?
- */
- if (index) {
- ali_write(0xf2, 0x00);
- }
- ali_write(0xf2, 0x0c);
- }
- ALI_CLOSE();
-
-}
-
-void ali512x_set_uart2_irda(int enabled)
-{
- ALI_OPEN();
- ALI_SELDEV(5);
-
- ali_write(0xf1, enabled?0x48:0x00); /* fullduplex IrDa */
- ALI_CLOSE();
-
-}
-
-void ali512x_set_rtc(int enabled, u16 io, u8 irq)
-{
- ALI_OPEN();
- ALI_SELDEV(6);
-
- ali_write(0x30, enabled?1:0);
- if (enabled) {
- ali_write(0x60, io >> 8);
- ali_write(0x61, io & 0xff);
- ali_write(0x70, irq);
-
- ali_write(0xf0, 0x00);
- }
- ALI_CLOSE();
-}
-
-void ali512x_set_kbc(int enabled, u8 kbc_irq, u8 mouse_irq)
-{
- ALI_OPEN();
- ALI_SELDEV(7);
-
- ali_write(0x30, enabled?1:0);
- if (enabled) {
- ali_write(0x70, kbc_irq);
- ali_write(0x72, mouse_irq);
-
- ali_write(0xf0, 0x00);
- }
- ALI_CLOSE();
-}
-
-
-/* Common I/O
- *
- * (This descripotsion is base on several incompete sources
- * since I have not been able to obtain any datasheet for the device
- * there may be some mis-understandings burried in here.
- * -- Daniel daniel@omicron.se)
- *
- * There are 22 CIO pins numbered
- * 10-17
- * 20-25
- * 30-37
- *
- * 20-24 are dedicated CIO pins, the other 17 are muliplexed with
- * other functions.
- *
- * Secondary
- * CIO Pin Function Decription
- * =======================================================
- * CIO10 IRQIN1 Interrupt input 1?
- * CIO11 IRQIN2 Interrupt input 2?
- * CIO12 IRRX IrDa Receive
- * CIO13 IRTX IrDa Transmit
- * CIO14 P21 KBC P21 fucntion
- * CIO15 P20 KBC P21 fucntion
- * CIO16 I2C_CLK I2C Clock
- * CIO17 I2C_DAT I2C Data
- *
- * CIO20 -
- * CIO21 -
- * CIO22 -
- * CIO23 -
- * CIO24 -
- * CIO25 LOCK Keylock
- *
- * CIO30 KBC_CLK Keybaord Clock
- * CIO31 CS0J General Chip Select decoder CS0J
- * CIO32 CS1J General Chip Select decoder CS1J
- * CIO33 ALT_KCLK Alternative Keyboard Clock
- * CIO34 ALT_KDAT Alternative Keyboard Data
- * CIO35 ALT_MCLK Alternative Mouse Clock
- * CIO36 ALT_MDAT Alternative Mouse Data
- * CIO37 ALT_KBC Alternative KBC select
- *
- * The CIO use a double indirect address scheme.
- *
- * Reigster 3 in the SIO is used to selectg where the CIO
- * I/O registers show up under function 8. Note that these
- * registers clash with the CIO function select regsters,
- * below.
- *
- * SIO reigster 3 (CIO Address Selection) bit definitions:
- * bit 7 CIO data register enabled
- * bit 1-0 CIO indirect registers select
- * 0 index = 0xE0 data = 0xE1
- * 1 index = 0xE2 data = 0xE3
- * 2 index = 0xE4 data = 0xE5
- * 3 index = 0xEA data = 0xEB
- *
- * There are three CIO I/O register accessed via CIO index and CIO data
- * 0x01 CIO 10-17 data
- * 0x02 CIO 20-25 data (bits 7-6 unused)
- * 0x03 CIO 30-37 data
- *
- *
- * The pin function is accessed through normal
- * SIO registers, each register have the same format:
- *
- * Bit Function Value
- * 0 Input/output 1=input
- * 1 Polarity of signal 1=inverted
- * 2 Unused ??
- * 3 Function (normal or special) 1=special
- * 7-4 Unused
- *
- * SIO REG
- * 0xe0 CIO 10 Config
- * 0xe1 CIO 11 Config
- * 0xe2 CIO 12 Config
- * 0xe3 CIO 13 Config
- * 0xe4 CIO 14 Config
- * 0xe5 CIO 15 Config
- * 0xe6 CIO 16 Config
- * 0xe7 CIO 16 Config
- *
- * 0xe8 CIO 20 Config
- * 0xe9 CIO 21 Config
- * 0xea CIO 22 Config
- * 0xeb CIO 23 Config
- * 0xec CIO 24 Config
- * 0xed CIO 25 Config
- *
- * 0xf5 CIO 30 Config
- * 0xf6 CIO 31 Config
- * 0xf7 CIO 32 Config
- * 0xf8 CIO 33 Config
- * 0xf9 CIO 34 Config
- * 0xfa CIO 35 Config
- * 0xfb CIO 36 Config
- * 0xfc CIO 37 Config
- *
- */
-
-void ali512x_set_cio(int enabled)
-{
- int i;
-
- ALI_OPEN();
- ali_write(0x3, 3); /* Disable CIO data register */
-
- ALI_SELDEV(8);
- ali_write(0x30, enabled?1:0);
-
- /* set all pins to input to start with */
- for (i=0xe0;i<0xee;i++) {
- ali_write(i, 1);
- }
- for (i=0xf5;i<0xfe;i++) {
- ali_write(i, 1);
- }
-
- ALI_CLOSE();
-}
-
-void ali512x_cio_function(int pin, int special, int inv, int input)
-{
- u8 data;
- u8 addr;
-
-
- /* valid pins are 10-17, 20-25 and 30-37 */
- if (pin >= 10 && pin <= 17) {
- addr = 0xe0+(pin-10);
- } else if (pin >= 20 && pin <= 25) {
- addr = 0xe8+(pin-20);
- } else if (pin >= 30 && pin <= 37) {
- addr = 0xf5+(pin-30);
- } else {
- return;
- }
-
- ALI_OPEN();
- ALI_SELDEV(8);
-
- ali_write(0x03, 0x03); /* Disable CIO data register */
-
- data=0;
- if (special) {
- data |= 0x08;
- } else {
- if (inv) {
- data |= 0x02;
- }
- if (input) {
- data |= 0x01;
- }
- }
-
- ali_write(addr, data);
-
- ALI_CLOSE();
-}
-
-void ali512x_cio_out(int pin, int value)
-{
- u8 reg;
- u8 data;
- u8 bit;
-
- /* valid pins are 10-17, 20-25 and 30-37 */
- if (pin >= 10 && pin <= 17) {
- reg = 1;
- pin -= 10;
- } else if (pin >= 20 && pin <= 25) {
- reg = 2;
- pin -= 20;
- } else if (pin >= 30 && pin <= 37) {
- reg = 3;
- pin -= 30;
- } else {
- return;
- }
- bit = 1 << pin;
-
- ALI_OPEN();
- ALI_SELDEV(8);
-
- ali_write(0x03, 0x83); /* Enable CIO data register, use data port at 0xea */
-
- ali_write(0xea, reg); /* select I/O register */
- data = ali_read(0xeb);
- if (value) {
- data |= bit;
- } else {
- data &= ~bit;
- }
- ali_write(0xeb, data);
- ali_write(0xea, 0); /* select register 0 */
- ali_write(0x03, 0x03); /* Disable CIO data register */
- ALI_CLOSE();
-}
-
-int ali512x_cio_in(int pin)
-{
- u8 reg;
- u8 data;
- u8 bit;
-
- /* valid pins are 10-17, 20-25 and 30-37 */
- if (pin >= 10 && pin <= 17) {
- reg = 1;
- pin -= 10;
- } else if (pin >= 20 && pin <= 25) {
- reg = 2;
- pin -= 20;
- } else if (pin >= 30 && pin <= 37) {
- reg = 3;
- pin -= 30;
- } else {
- return -1;
- }
- bit = 1 << pin;
-
- ALI_OPEN();
- ALI_SELDEV(8);
-
- ali_write(0x03, 0x83); /* Enable CIO data register, use data port at 0xea */
-
- ali_write(0xea, reg); /* select I/O register */
- data = ali_read(0xeb);
- ali_write(0xea, 0); /* select register 0 */
- ali_write(0x03, 0x03); /* Disable CIO data register */
- ALI_CLOSE();
-
- return data & bit;
-}
-
-
diff --git a/lib_i386/ic/sc520.c b/lib_i386/ic/sc520.c
deleted file mode 100644
index d202625bb5a..00000000000
--- a/lib_i386/ic/sc520.c
+++ /dev/null
@@ -1,348 +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
- */
-
-/* stuff specific for the sc520,
- * but idependent of implementation */
-
-
-#include <common.h>
-#include <config.h>
-#include <pci.h>
-#include <asm/io.h>
-#include <asm/pci.h>
-#include <asm/ic/sc520.h>
-
-/*
- * utility functions for boards based on the AMD sc520
- *
- * void write_mmcr_byte(u16 mmcr, u8 data)
- * void write_mmcr_word(u16 mmcr, u16 data)
- * void write_mmcr_long(u16 mmcr, u32 data)
- *
- * u8 read_mmcr_byte(u16 mmcr)
- * u16 read_mmcr_word(u16 mmcr)
- * u32 read_mmcr_long(u16 mmcr)
- *
- * void init_sc520(void)
- * unsigned long init_sc520_dram(void)
- * void pci_sc520_init(struct pci_controller *hose)
- *
- * void reset_timer(void)
- * ulong get_timer(ulong base)
- * void set_timer(ulong t)
- * void udelay(unsigned long usec)
- *
- */
-
-static u32 mmcr_base= 0xfffef000;
-
-void write_mmcr_byte(u16 mmcr, u8 data)
-{
- writeb(data, mmcr+mmcr_base);
-}
-
-void write_mmcr_word(u16 mmcr, u16 data)
-{
- writew(data, mmcr+mmcr_base);
-}
-
-void write_mmcr_long(u16 mmcr, u32 data)
-{
- writel(data, mmcr+mmcr_base);
-}
-
-u8 read_mmcr_byte(u16 mmcr)
-{
- return readb(mmcr+mmcr_base);
-}
-
-u16 read_mmcr_word(u16 mmcr)
-{
- return readw(mmcr+mmcr_base);
-}
-
-u32 read_mmcr_long(u16 mmcr)
-{
- return readl(mmcr+mmcr_base);
-}
-
-
-void init_sc520(void)
-{
- DECLARE_GLOBAL_DATA_PTR;
-
- /* Set the UARTxCTL register at it's slower,
- * baud clock giving us a 1.8432 MHz reference
- */
- write_mmcr_byte(SC520_UART1CTL, 7);
- write_mmcr_byte(SC520_UART2CTL, 7);
-
- /* first set the timer pin mapping */
- write_mmcr_byte(SC520_CLKSEL, 0x72); /* no clock frequency selected, use 1.1892MHz */
-
- /* enable PCI bus arbitrer */
- write_mmcr_byte(SC520_SYSARBCTL,0x02); /* enable concurrent mode */
-
- write_mmcr_word(SC520_SYSARBMENB,0x1f); /* enable external grants */
- write_mmcr_word(SC520_HBCTL,0x04); /* enable posted-writes */
-
-
- if (CFG_SC520_HIGH_SPEED) {
- write_mmcr_byte(SC520_CPUCTL, 0x2); /* set it to 133 MHz and write back */
- gd->cpu_clk = 133000000;
- printf("## CPU Speed set to 133MHz\n");
- } else {
- write_mmcr_byte(SC520_CPUCTL, 1); /* set CPU to 100 MHz and write back cache */
- printf("## CPU Speed set to 100MHz\n");
- gd->cpu_clk = 100000000;
- }
-
-
- /* wait at least one millisecond */
- asm("movl $0x2000,%%ecx\n"
- "wait_loop: pushl %%ecx\n"
- "popl %%ecx\n"
- "loop wait_loop\n": : : "ecx");
-
- /* turn on the SDRAM write buffer */
- write_mmcr_byte(SC520_DBCTL, 0x11);
-
- /* turn on the cache and disable write through */
- asm("movl %%cr0, %%eax\n"
- "andl $0x9fffffff, %%eax\n"
- "movl %%eax, %%cr0\n" : : : "eax");
-}
-
-unsigned long init_sc520_dram(void)
-{
- DECLARE_GLOBAL_DATA_PTR;
- bd_t *bd = gd->bd;
-
- u32 dram_present=0;
- u32 dram_ctrl;
-
- int val;
-
- int cas_precharge_delay = CFG_SDRAM_PRECHARGE_DELAY;
- int refresh_rate = CFG_SDRAM_REFRESH_RATE;
- int ras_cas_delay = CFG_SDRAM_RAS_CAS_DELAY;
-
- /* set SDRAM speed here */
-
- refresh_rate/=78;
- if (refresh_rate<=1) {
- val = 0; /* 7.8us */
- } else if (refresh_rate==2) {
- val = 1; /* 15.6us */
- } else if (refresh_rate==3 || refresh_rate==4) {
- val = 2; /* 31.2us */
- } else {
- val = 3; /* 62.4us */
- }
- write_mmcr_byte(SC520_DRCCTL, (read_mmcr_byte(SC520_DRCCTL) & 0xcf) | (val<<4));
-
- val = read_mmcr_byte(SC520_DRCTMCTL);
- val &= 0xf0;
-
- if (cas_precharge_delay==3) {
- val |= 0x04; /* 3T */
- } else if (cas_precharge_delay==4) {
- val |= 0x08; /* 4T */
- } else if (cas_precharge_delay>4) {
- val |= 0x0c;
- }
-
- if (ras_cas_delay > 3) {
- val |= 2;
- } else {
- val |= 1;
- }
- write_mmcr_byte(SC520_DRCTMCTL, val);
-
-
- /* We read-back the configuration of the dram
- * controller that the assembly code wrote */
- dram_ctrl = read_mmcr_long(SC520_DRCBENDADR);
-
-
- bd->bi_dram[0].start = 0;
- if (dram_ctrl & 0x80) {
- /* bank 0 enabled */
- dram_present = bd->bi_dram[1].start = (dram_ctrl & 0x7f) << 22;
- bd->bi_dram[0].size = bd->bi_dram[1].start;
-
- } else {
- bd->bi_dram[0].size = 0;
- bd->bi_dram[1].start = bd->bi_dram[0].start;
- }
-
- if (dram_ctrl & 0x8000) {
- /* bank 1 enabled */
- dram_present = bd->bi_dram[2].start = (dram_ctrl & 0x7f00) << 14;
- bd->bi_dram[1].size = bd->bi_dram[2].start - bd->bi_dram[1].start;
- } else {
- bd->bi_dram[1].size = 0;
- bd->bi_dram[2].start = bd->bi_dram[1].start;
- }
-
- if (dram_ctrl & 0x800000) {
- /* bank 2 enabled */
- dram_present = bd->bi_dram[3].start = (dram_ctrl & 0x7f0000) << 6;
- bd->bi_dram[2].size = bd->bi_dram[3].start - bd->bi_dram[2].start;
- } else {
- bd->bi_dram[2].size = 0;
- bd->bi_dram[3].start = bd->bi_dram[2].start;
- }
-
- if (dram_ctrl & 0x80000000) {
- /* bank 3 enabled */
- dram_present = (dram_ctrl & 0x7f000000) >> 2;
- bd->bi_dram[3].size = dram_present - bd->bi_dram[3].start;
- } else {
- bd->bi_dram[3].size = 0;
- }
-
-
-#if 0
- printf("Configured %d bytes of dram\n", dram_present);
-#endif
- gd->ram_size = dram_present;
-
- return dram_present;
-}
-
-
-#ifdef CONFIG_PCI
-
-
-
-void pci_sc520_init(struct pci_controller *hose)
-{
- hose->first_busno = 0;
- hose->last_busno = 0xff;
-
- /* System memory space */
- pci_set_region(hose->regions + 0,
- SC520_PCI_MEMORY_BUS,
- SC520_PCI_MEMORY_PHYS,
- SC520_PCI_MEMORY_SIZE,
- PCI_REGION_MEM | PCI_REGION_MEMORY);
-
- /* PCI memory space */
- pci_set_region(hose->regions + 1,
- SC520_PCI_MEM_BUS,
- SC520_PCI_MEM_PHYS,
- SC520_PCI_MEM_SIZE,
- PCI_REGION_MEM);
-
- /* ISA/PCI memory space */
- pci_set_region(hose->regions + 2,
- SC520_ISA_MEM_BUS,
- SC520_ISA_MEM_PHYS,
- SC520_ISA_MEM_SIZE,
- PCI_REGION_MEM);
-
- /* PCI I/O space */
- pci_set_region(hose->regions + 3,
- SC520_PCI_IO_BUS,
- SC520_PCI_IO_PHYS,
- SC520_PCI_IO_SIZE,
- PCI_REGION_IO);
-
- /* ISA/PCI I/O space */
- pci_set_region(hose->regions + 4,
- SC520_ISA_IO_BUS,
- SC520_ISA_IO_PHYS,
- SC520_ISA_IO_SIZE,
- PCI_REGION_IO);
-
- hose->region_count = 5;
-
- pci_setup_type1(hose,
- SC520_REG_ADDR,
- SC520_REG_DATA);
-
- pci_register_hose(hose);
-
- hose->last_busno = pci_hose_scan(hose);
-
- /* enable target memory acceses on host brige */
- pci_write_config_word(0, PCI_COMMAND,
- PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
-
-}
-
-
-#endif
-
-#ifdef CFG_TIMER_SC520
-
-
-void reset_timer(void)
-{
- write_mmcr_word(SC520_GPTMR0CNT, 0);
- write_mmcr_word(SC520_GPTMR0CTL, 0x6001);
-
-}
-
-ulong get_timer(ulong base)
-{
- /* fixme: 30 or 33 */
- return read_mmcr_word(SC520_GPTMR0CNT) / 33;
-}
-
-void set_timer(ulong t)
-{
- /* FixMe: use two cascade coupled timers */
- write_mmcr_word(SC520_GPTMR0CTL, 0x4001);
- write_mmcr_word(SC520_GPTMR0CNT, t*33);
- write_mmcr_word(SC520_GPTMR0CTL, 0x6001);
-}
-
-
-void udelay(unsigned long usec)
-{
- int m=0;
- long u;
-
- read_mmcr_word(SC520_SWTMRMILLI);
- read_mmcr_word(SC520_SWTMRMICRO);
-
-#if 0
- /* do not enable this line, udelay is used in the serial driver -> recursion */
- printf("udelay: %ld m.u %d.%d tm.tu %d.%d\n", usec, m, u, tm, tu);
-#endif
- while (1) {
-
- m += read_mmcr_word(SC520_SWTMRMILLI);
- u = read_mmcr_word(SC520_SWTMRMICRO) + (m * 1000);
-
- if (usec <= u) {
- break;
- }
- }
-}
-
-#endif
-
-
diff --git a/lib_i386/ic/sc520_asm.S b/lib_i386/ic/sc520_asm.S
deleted file mode 100644
index 72110c4a0aa..00000000000
--- a/lib_i386/ic/sc520_asm.S
+++ /dev/null
@@ -1,530 +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
- */
-
-/* This file is largely based on code obtned from AMD. AMD's original
- * copyright is included below
- */
-
-/*
- * =============================================================================
- *
- * Copyright 1999 Advanced Micro Devices, Inc.
- *
- * This software is the property of Advanced Micro Devices, Inc (AMD) which
- * specifically grants the user the right to modify, use and distribute this
- * software provided this COPYRIGHT NOTICE is not removed or altered. All
- * other rights are reserved by AMD.
- *
- * THE MATERIALS ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTY
- * OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT OF
- * THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY PARTICULAR PURPOSE.
- * IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER
- * (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
- * INTERRUPTION, LOSS OF INFORMAITON) ARISING OUT OF THE USE OF OR INABILITY
- * TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGES. BECAUSE SOME JURSIDICTIONS PROHIBIT THE EXCLUSION OR
- * LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE
- * LIMITATION MAY NOT APPLY TO YOU.
- *
- * AMD does not assume any responsibility for any errors that may appear in
- * the Materials nor any responsibility to support or update the Materials.
- * AMD retains the right to make changes to its test specifications at any
- * time, without notice.
- *
- * So that all may benefit from your experience, please report any problems
- * or suggestions about this software back to AMD. Please include your name,
- * company, telephone number, AMD product requiring support and question or
- * problem encountered.
- *
- * Advanced Micro Devices, Inc. Worldwide support and contact
- * Embedded Processor Division information available at:
- * Systems Engineering epd.support@amd.com
- * 5204 E. Ben White Blvd. -or-
- * Austin, TX 78741 http://www.amd.com/html/support/techsup.html
- * ============================================================================
- */
-
-
-/*******************************************************************************
- * AUTHOR : Buddy Fey - Original.
- *******************************************************************************
- */
-
-
-/*******************************************************************************
- * FUNCTIONAL DESCRIPTION:
- * This routine is called to autodetect the geometry of the DRAM.
- *
- * This routine is called to determine the number of column bits for the DRAM
- * devices in this external bank. This routine assumes that the external bank
- * has been configured for an 11-bit column and for 4 internal banks. This gives
- * us the maximum address reach in memory. By writing a test value to the max
- * address and locating where it aliases to, we can determine the number of valid
- * column bits.
- *
- * This routine is called to determine the number of internal banks each DRAM
- * device has. The external bank (under test) is configured for maximum reach
- * with 11-bit columns and 4 internal banks. This routine will write to a max
- * address (BA1 and BA0 = 1) and then read from an address with BA1=0 to see if
- * that column is a "don't care". If BA1 does not affect write/read of data,
- * then this device has only 2 internal banks.
- *
- * This routine is called to determine the ending address for this external
- * bank of SDRAM. We write to a max address with a data value and then disable
- * row address bits looking for "don't care" locations. Each "don't care" bit
- * represents a dividing of the maximum density (128M) by 2. By dividing the
- * maximum of 32 4M chunks in an external bank down by all the "don't care" bits
- * determined during sizing, we set the proper density.
- *
- * WARNINGS.
- * bp must be preserved because it is used for return linkage.
- *
- * EXIT
- * nothing returned - but the memory subsystem is enabled
- *******************************************************************************
- */
-
-.section .text
-.equ DRCCTL, 0x0fffef010 /* DRAM control register */
-.equ DRCTMCTL, 0x0fffef012 /* DRAM timing control register */
-.equ DRCCFG, 0x0fffef014 /* DRAM bank configuration register */
-.equ DRCBENDADR, 0x0fffef018 /* DRAM bank ending address register */
-.equ ECCCTL, 0x0fffef020 /* DRAM ECC control register */
-.equ DBCTL, 0x0fffef040 /* DRAM buffer control register */
-
-.equ CACHELINESZ, 0x00000010 /* size of our cache line (read buffer) */
-.equ COL11_ADR, 0x0e001e00 /* 11 col addrs */
-.equ COL10_ADR, 0x0e000e00 /* 10 col addrs */
-.equ COL09_ADR, 0x0e000600 /* 9 col addrs */
-.equ COL08_ADR, 0x0e000200 /* 8 col addrs */
-.equ ROW14_ADR, 0x0f000000 /* 14 row addrs */
-.equ ROW13_ADR, 0x07000000 /* 13 row addrs */
-.equ ROW12_ADR, 0x03000000 /* 12 row addrs */
-.equ ROW11_ADR, 0x01000000 /* 11 row addrs/also bank switch */
-.equ ROW10_ADR, 0x00000000 /* 10 row addrs/also bank switch */
-.equ COL11_DATA, 0x0b0b0b0b /* 11 col addrs */
-.equ COL10_DATA, 0x0a0a0a0a /* 10 col data */
-.equ COL09_DATA, 0x09090909 /* 9 col data */
-.equ COL08_DATA, 0x08080808 /* 8 col data */
-.equ ROW14_DATA, 0x3f3f3f3f /* 14 row data (MASK) */
-.equ ROW13_DATA, 0x1f1f1f1f /* 13 row data (MASK) */
-.equ ROW12_DATA, 0x0f0f0f0f /* 12 row data (MASK) */
-.equ ROW11_DATA, 0x07070707 /* 11 row data/also bank switch (MASK) */
-.equ ROW10_DATA, 0xaaaaaaaa /* 10 row data/also bank switch (MASK) */
-
-
- /*
- * initialize dram controller registers
- */
-.globl mem_init
-mem_init:
- xorw %ax,%ax
- movl $DBCTL, %edi
-fs movb %al, (%edi) /* disable write buffer */
-
- movl $ECCCTL, %edi
-fs movb %al, (%edi) /* disable ECC */
-
- movl $DRCTMCTL, %edi
- movb $0x1E,%al /* Set SDRAM timing for slowest */
-fs movb %al, (%edi)
-
- /*
- * setup loop to do 4 external banks starting with bank 3
- */
- movl $0xff000000,%eax /* enable last bank and setup */
- movl $DRCBENDADR, %edi /* ending address register */
-fs movl %eax, (%edi)
-
- movl $DRCCFG, %edi /* setup */
- movw $0xbbbb,%ax /* dram config register for */
-fs movw %ax, (%edi)
-
- /*
- * issue a NOP to all DRAMs
- */
- movl $DRCCTL, %edi /* setup DRAM control register with */
- movb $0x1,%al /* Disable refresh,disable write buffer */
-fs movb %al, (%edi)
- movl $CACHELINESZ, %esi /* just a dummy address to write for */
-fs movw %ax, (%esi)
- /*
- * delay for 100 usec? 200?
- * ******this is a cludge for now *************
- */
- movw $100,%cx
-sizdelay:
- loop sizdelay /* we need 100 usec here */
- /***********************************************/
-
- /*
- * issue all banks precharge
- */
- movb $0x2,%al /* All banks precharge */
-fs movb %al, (%edi)
-fs movw %ax, (%esi)
-
- /*
- * issue 2 auto refreshes to all banks
- */
- movb $0x4,%al /* Auto refresh cmd */
-fs movb %al, (%edi)
- movw $2,%cx
-refresh1:
-fs movw %ax, (%esi)
- loop refresh1
-
- /*
- * issue LOAD MODE REGISTER command
- */
- movb $0x3,%al /* Load mode register cmd */
-fs movb %al, (%edi)
-fs movw %ax, (%esi)
-
- /*
- * issue 8 more auto refreshes to all banks
- */
- movb $0x4,%al /* Auto refresh cmd */
-fs movb %al, (%edi)
- movw $8,%cx
-refresh2:
-fs movw %ax, (%esi)
- loop refresh2
-
- /*
- * set control register to NORMAL mode
- */
- movb $0x0,%al /* Normal mode value */
-fs movb %al, (%edi)
-
- /*
- * size dram starting with external bank 3 moving to external bank 0
- */
- movl $0x3,%ecx /* start with external bank 3 */
-
-nextbank:
-
- /*
- * write col 11 wrap adr
- */
- movl $COL11_ADR, %esi /* set address to max col (11) wrap addr */
- movl $COL11_DATA, %eax /* pattern for max supported columns(11) */
-fs movl %eax, (%esi) /* write max col pattern at max col adr */
-fs movl (%esi), %ebx /* optional read */
- cmpl %ebx,%eax /* to verify write */
- jnz bad_ram /* this ram is bad */
- /*
- * write col 10 wrap adr
- */
-
- movl $COL10_ADR, %esi /* set address to 10 col wrap address */
- movl $COL10_DATA, %eax /* pattern for 10 col wrap */
-fs movl %eax, (%esi) /* write 10 col pattern @ 10 col wrap adr */
-fs movl (%esi), %ebx /* optional read */
- cmpl %ebx,%eax /* to verify write */
- jnz bad_ram /* this ram is bad */
- /*
- * write col 9 wrap adr
- */
- movl $COL09_ADR, %esi /* set address to 9 col wrap address */
- movl $COL09_DATA, %eax /* pattern for 9 col wrap */
-fs movl %eax, (%esi) /* write 9 col pattern @ 9 col wrap adr */
-fs movl (%esi), %ebx /* optional read */
- cmpl %ebx,%eax /* to verify write */
- jnz bad_ram /* this ram is bad */
- /*
- * write col 8 wrap adr
- */
- movl $COL08_ADR, %esi /* set address to min(8) col wrap address */
- movl $COL08_DATA, %eax /* pattern for min (8) col wrap */
-fs movl %eax, (%esi) /* write min col pattern @ min col adr */
-fs movl (%esi), %ebx /* optional read */
- cmpl %ebx,%eax /* to verify write */
- jnz bad_ram /* this ram is bad */
- /*
- * write row 14 wrap adr
- */
- movl $ROW14_ADR, %esi /* set address to max row (14) wrap addr */
- movl $ROW14_DATA, %eax /* pattern for max supported rows(14) */
-fs movl %eax, (%esi) /* write max row pattern at max row adr */
-fs movl (%esi), %ebx /* optional read */
- cmpl %ebx,%eax /* to verify write */
- jnz bad_ram /* this ram is bad */
- /*
- * write row 13 wrap adr
- */
- movl $ROW13_ADR, %esi /* set address to 13 row wrap address */
- movl $ROW13_DATA, %eax /* pattern for 13 row wrap */
-fs movl %eax, (%esi) /* write 13 row pattern @ 13 row wrap adr */
-fs movl (%esi), %ebx /* optional read */
- cmpl %ebx,%eax /* to verify write */
- jnz bad_ram /* this ram is bad */
- /*
- * write row 12 wrap adr
- */
- movl $ROW12_ADR, %esi /* set address to 12 row wrap address */
- movl $ROW12_DATA, %eax /* pattern for 12 row wrap */
-fs movl %eax, (%esi) /* write 12 row pattern @ 12 row wrap adr */
-fs movl (%esi), %ebx /* optional read */
- cmpl %ebx,%eax /* to verify write */
- jnz bad_ram /* this ram is bad */
- /*
- * write row 11 wrap adr
- */
- movl $ROW11_ADR, %edi /* set address to 11 row wrap address */
- movl $ROW11_DATA, %eax /* pattern for 11 row wrap */
-fs movl %eax, (%edi) /* write 11 row pattern @ 11 row wrap adr */
-fs movl (%edi), %ebx /* optional read */
- cmpl %ebx,%eax /* to verify write */
- jnz bad_ram /* this ram is bad */
- /*
- * write row 10 wrap adr --- this write is really to determine number of banks
- */
- movl $ROW10_ADR, %edi /* set address to 10 row wrap address */
- movl $ROW10_DATA, %eax /* pattern for 10 row wrap (AA) */
-fs movl %eax, (%edi) /* write 10 row pattern @ 10 row wrap adr */
-fs movl (%edi), %ebx /* optional read */
- cmpl %ebx,%eax /* to verify write */
- jnz bad_ram /* this ram is bad */
- /*
- * read data @ row 12 wrap adr to determine * banks,
- * and read data @ row 14 wrap adr to determine * rows.
- * if data @ row 12 wrap adr is not AA, 11 or 12 we have bad RAM.
- * if data @ row 12 wrap == AA, we only have 2 banks, NOT 4
- * if data @ row 12 wrap == 11 or 12, we have 4 banks,
- */
- xorw %di,%di /* value for 2 banks in DI */
-fs movl (%esi), %ebx /* read from 12 row wrap to check banks
- * (esi is setup from the write to row 12 wrap) */
- cmpl %ebx,%eax /* check for AA pattern (eax holds the aa pattern) */
- jz only2 /* if pattern == AA, we only have 2 banks */
-
- /* 4 banks */
-
- movw $8,%di /* value for 4 banks in DI (BNK_CNT bit) */
- cmpl $ROW11_DATA, %ebx /* only other legitimate values are 11 */
- jz only2
- cmpl $ROW12_DATA, %ebx /* and 12 */
- jnz bad_ram /* its bad if not 11 or 12! */
-
- /* fall through */
-only2:
- /*
- * validate row mask
- */
- movl $ROW14_ADR, %esi /* set address back to max row wrap addr */
-fs movl (%esi), %eax /* read actual number of rows @ row14 adr */
-
- cmpl $ROW11_DATA, %eax /* row must be greater than 11 pattern */
- jb bad_ram
-
- cmpl $ROW14_DATA, %eax /* and row must be less than 14 pattern */
- ja bad_ram
-
- cmpb %ah,%al /* verify all 4 bytes of dword same */
- jnz bad_ram
- movl %eax,%ebx
- shrl $16,%ebx
- cmpw %bx,%ax
- jnz bad_ram
- /*
- * read col 11 wrap adr for real column data value
- */
- movl $COL11_ADR, %esi /* set address to max col (11) wrap addr */
-fs movl (%esi), %eax /* read real col number at max col adr */
- /*
- * validate column data
- */
- cmpl $COL08_DATA, %eax /* col must be greater than 8 pattern */
- jb bad_ram
-
- cmpl $COL11_DATA, %eax /* and row must be less than 11 pattern */
- ja bad_ram
-
- subl $COL08_DATA, %eax /* normalize column data to zero */
- jc bad_ram
- cmpb %ah,%al /* verify all 4 bytes of dword equal */
- jnz bad_ram
- movl %eax,%edx
- shrl $16,%edx
- cmpw %dx,%ax
- jnz bad_ram
- /*
- * merge bank and col data together
- */
- addw %di,%dx /* merge of bank and col info in dl */
- /*
- * fix ending addr mask based upon col info
- */
- movb $3,%al
- subb %dh,%al /* dh contains the overflow from the bank/col merge */
- movb %bl,%dh /* bl contains the row mask (aa, 07, 0f, 1f or 3f) */
- xchgw %cx,%ax /* cx = ax = 3 or 2 depending on 2 or 4 bank device */
- shrb %cl,%dh /* */
- incb %dh /* ending addr is 1 greater than real end */
- xchgw %cx,%ax /* cx is bank number again */
- /*
- * issue all banks precharge
- */
-bad_reint:
- movl $DRCCTL, %esi /* setup DRAM control register with */
- movb $0x2,%al /* All banks precharge */
-fs movb %al, (%esi)
- movl $CACHELINESZ, %esi /* address to init read buffer */
-fs movw %ax, (%esi)
-
- /*
- * update ENDING ADDRESS REGISTER
- */
- movl $DRCBENDADR, %edi /* DRAM ending address register */
- movl %ecx,%ebx
- addl %ebx, %edi
-fs movb %dh, (%edi)
- /*
- * update CONFIG REGISTER
- */
- xorb %dh,%dh
- movw $0x00f,%bx
- movw %cx,%ax
- shlw $2,%ax
- xchgw %cx,%ax
- shlw %cl,%dx
- shlw %cl,%bx
- notw %bx
- xchgw %cx,%ax
- movl $DRCCFG, %edi
-fs mov (%edi), %ax
- andw %bx,%ax
- orw %dx,%ax
-fs movw %ax, (%edi)
- jcxz cleanup
-
- decw %cx
- movl %ecx,%ebx
- movl $DRCBENDADR, %edi /* DRAM ending address register */
- movb $0xff,%al
- addl %ebx, %edi
-fs movb %al, (%edi)
- /*
- * set control register to NORMAL mode
- */
- movl $DRCCTL, %esi /* setup DRAM control register with */
- movb $0x0,%al /* Normal mode value */
-fs movb %al, (%esi)
- movl $CACHELINESZ, %esi /* address to init read buffer */
-fs movw %ax, (%esi)
- jmp nextbank
-
-cleanup:
- movl $DRCBENDADR, %edi /* DRAM ending address register */
- movw $4,%cx
- xorw %ax,%ax
-cleanuplp:
-fs movb (%edi), %al
- orb %al,%al
- jz emptybank
-
- addb %ah,%al
- jns nottoomuch
-
- movb $0x7f,%al
-nottoomuch:
- movb %al,%ah
- orb $0x80,%al
-fs movb %al, (%edi)
-emptybank:
- incl %edi
- loop cleanuplp
-
-#if defined(CFG_SDRAM_CAS_LATENCY_2T) || defined(CFG_SDRAM_CAS_LATENCY_3T)
- /* set the CAS latency now since it is hard to do
- * when we run from the RAM */
- movl $DRCTMCTL, %edi /* DRAM timing register */
- movb (%edi), %al
-#ifdef CFG_SDRAM_CAS_LATENCY_2T
- andb $0xef, %al
-#endif
-#ifdef CFG_SDRAM_CAS_LATENCY_3T
- orb $0x10, %al
-#endif
- movb %al, (%edi)
-#endif
- movl $DRCCTL, %edi /* DRAM Control register */
- movb $0x3,%al /* Load mode register cmd */
-fs movb %al, (%edi)
-fs movw %ax, (%esi)
-
-
- movl $DRCCTL, %edi /* DRAM Control register */
- movb $0x18,%al /* Enable refresh and NORMAL mode */
-fs movb %al, (%edi)
-
- jmp dram_done
-
-bad_ram:
- xorl %edx,%edx
- xorl %edi,%edi
- jmp bad_reint
-
-dram_done:
-
- /* readback DRCBENDADR and return the number
- * of available ram bytes in %eax */
-
- movl $DRCBENDADR, %edi /* DRAM ending address register */
-
- movl (%edi), %eax
- movl %eax, %ecx
- andl $0x80000000, %ecx
- jz bank2
- andl $0x7f000000, %eax
- shrl $2, %eax
- movl %eax, %ebx
-
-bank2: movl (%edi), %eax
- movl %eax, %ecx
- andl $0x00800000, %ecx
- jz bank1
- andl $0x007f0000, %eax
- shll $6, %eax
- movl %eax, %ebx
-
-bank1: movl (%edi), %eax
- movl %eax, %ecx
- andl $0x00008000, %ecx
- jz bank0
- andl $0x00007f00, %eax
- shll $14, %eax
- movl %eax, %ebx
-
-bank0: movl (%edi), %eax
- movl %eax, %ecx
- andl $0x00000080, %ecx
- jz done
- andl $0x0000007f, %eax
- shll $22, %eax
- movl %eax, %ebx
-
-done: movl %ebx, %eax
-
- jmp *%ebp
diff --git a/lib_i386/pci.c b/lib_i386/pci.c
new file mode 100644
index 00000000000..acd1d25fa92
--- /dev/null
+++ b/lib_i386/pci.c
@@ -0,0 +1,156 @@
+/*
+ * (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 <asm/io.h>
+#include <asm/pci.h>
+
+#ifdef CONFIG_PCI
+#undef PCI_ROM_SCAN_VERBOSE
+
+int pci_shadow_rom(pci_dev_t dev, unsigned char *dest)
+{
+ struct pci_controller *hose;
+ int res = -1;
+ int i;
+
+ u32 rom_addr;
+ u32 addr_reg;
+ u32 size;
+
+ u16 vendor;
+ u16 device;
+ u32 class_code;
+
+ hose = pci_bus_to_hose(PCI_BUS(dev));
+#if 0
+ printf("pci_shadow_rom() asked to shadow device %x to %x\n",
+ dev, (u32)dest);
+#endif
+ pci_read_config_word(dev, PCI_VENDOR_ID, &vendor);
+ pci_read_config_word(dev, PCI_DEVICE_ID, &device);
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_code);
+
+ class_code &= 0xffffff00;
+ class_code >>= 8;
+
+#if 0
+ printf("PCI Header Vendor %04x device %04x class %06x\n",
+ vendor, device, class_code);
+#endif
+ /* Enable the rom addess decoder */
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, PCI_ROM_ADDRESS_MASK);
+ pci_read_config_dword(dev, PCI_ROM_ADDRESS, &addr_reg);
+
+ if (!addr_reg) {
+ /* register unimplemented */
+ printf("pci_chadow_rom: device do not seem to have a rom\n");
+ return -1;
+ }
+
+ size = (~(addr_reg&PCI_ROM_ADDRESS_MASK))+1;
+
+#if 0
+ printf("ROM is %d bytes\n", size);
+#endif
+ rom_addr = pci_get_rom_window(hose, size);
+#if 0
+ printf("ROM mapped at %x \n", rom_addr);
+#endif
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS,
+ pci_phys_to_mem(dev, rom_addr)
+ |PCI_ROM_ADDRESS_ENABLE);
+
+
+
+ for (i=rom_addr;i<rom_addr+size; i+=512) {
+
+
+ if (readw(i) == 0xaa55) {
+ u32 pci_data;
+#ifdef PCI_ROM_SCAN_VERBOSE
+ printf("ROM signature found\n");
+#endif
+ pci_data = readw(0x18+i);
+ pci_data += i;
+
+ if (0==memcmp((void*)pci_data, "PCIR", 4)) {
+#ifdef PCI_ROM_SCAN_VERBOSE
+ printf("Fount PCI rom image at offset %d\n", i-rom_addr);
+ printf("Vendor %04x device %04x class %06x\n",
+ readw(pci_data+4), readw(pci_data+6),
+ readl(pci_data+0x0d)&0xffffff);
+ printf("%s\n",
+ (readw(pci_data+0x15) &0x80)?
+ "Last image":"More images follow");
+ switch (readb(pci_data+0x14)) {
+ case 0:
+ printf("X86 code\n");
+ break;
+ case 1:
+ printf("Openfirmware code\n");
+ break;
+ case 2:
+ printf("PARISC code\n");
+ break;
+ }
+ printf("Image size %d\n", readw(pci_data+0x10) * 512);
+#endif
+ /* FixMe: I think we should compare the class code
+ * bytes as well but I have no reference on the
+ * exact order of these bytes in the PCI ROM header */
+ if (readw(pci_data+4) == vendor &&
+ readw(pci_data+6) == device &&
+ /* (readl(pci_data+0x0d)&0xffffff) == class_code && */
+ readb(pci_data+0x14) == 0 /* x86 code image */ ) {
+#ifdef PCI_ROM_SCAN_VERBOSE
+ printf("Suitable ROM image found, copying\n");
+#endif
+ memmove(dest, (void*)rom_addr, readw(pci_data+0x10) * 512);
+ res = 0;
+ break;
+
+ }
+ if (readw(pci_data+0x15) &0x80) {
+ break;
+ }
+ }
+ }
+
+ }
+
+#ifdef PCI_ROM_SCAN_VERBOSE
+ if (res) {
+ printf("No suitable image found\n");
+ }
+#endif
+ /* disable PAR register and PCI device ROM address devocer */
+ pci_remove_rom_window(hose, rom_addr);
+
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
+
+ return res;
+}
+
+#endif
diff --git a/lib_i386/realmode.c b/lib_i386/realmode.c
index 27d46938250..d7bb81c57f5 100644
--- a/lib_i386/realmode.c
+++ b/lib_i386/realmode.c
@@ -33,25 +33,33 @@
extern char realmode_enter;
-
-int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out)
+int realmode_setup(void)
{
-
- /* setup out thin bios emulation */
- if (bios_setup()) {
- return -1;
- }
-
/* copy the realmode switch code */
if (i386boot_realmode_size > (REALMODE_MAILBOX-REALMODE_BASE)) {
printf("realmode switch too large (%ld bytes, max is %d)\n",
- i386boot_realmode_size, (int)(REALMODE_MAILBOX-REALMODE_BASE));
+ i386boot_realmode_size, (REALMODE_MAILBOX-REALMODE_BASE));
return -1;
}
memcpy(REALMODE_BASE, (void*)i386boot_realmode, i386boot_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 (3>(in->esp & 0xffff)) {
@@ -59,12 +67,30 @@ int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out)
}
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&1;
+}
+
diff --git a/lib_i386/realmode_switch.S b/lib_i386/realmode_switch.S
index 9f212c2e8e1..17adcbd7fd1 100644
--- a/lib_i386/realmode_switch.S
+++ b/lib_i386/realmode_switch.S
@@ -50,7 +50,6 @@
.section .realmode, "ax"
.code16
-
/* 16bit protected mode code here */
.globl realmode_enter
realmode_enter:
diff --git a/lib_i386/video.c b/lib_i386/video.c
new file mode 100644
index 00000000000..776022e9242
--- /dev/null
+++ b/lib_i386/video.c
@@ -0,0 +1,238 @@
+/*
+ * (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 <devices.h>
+#include <i8042.h>
+#include <asm/ptrace.h>
+#include <asm/realmode.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+
+
+/* basic textmode I/O from linux kernel */
+static char *vidmem = (char *)0xb8000;
+static int vidport;
+static int lines, cols;
+static int orig_x, orig_y;
+
+static void beep(int dur)
+{
+ int i;
+
+ outb_p(3, 0x61);
+ for (i=0;i<10*dur;i++) {
+ udelay(1000);
+ }
+ outb_p(0, 0x61);
+}
+
+static void scroll(void)
+{
+ int i;
+
+ memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
+ for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
+ vidmem[i] = ' ';
+}
+
+static void __video_putc(const char c, int *x, int *y)
+{
+ if (c == '\n') {
+ (*x) = 0;
+ if ( ++(*y) >= lines ) {
+ scroll();
+ (*y)--;
+ }
+ } else if (c == '\b') {
+ if ((*x) != 0) {
+ --(*x);
+ vidmem [ ( (*x) + cols * (*y) ) * 2 ] = ' ';
+ }
+ } else if (c == '\r') {
+ (*x) = 0;
+
+ } else if (c == '\a') {
+ beep(3);
+
+ } else if (c == '\t') {
+ __video_putc(' ', x, y);
+ __video_putc(' ', x, y);
+ __video_putc(' ', x, y);
+ __video_putc(' ', x, y);
+ __video_putc(' ', x, y);
+ __video_putc(' ', x, y);
+ __video_putc(' ', x, y);
+ __video_putc(' ', x, y);
+ } else if (c == '\v') {
+ switch ((*x) % 8) {
+ case 0:
+ __video_putc(' ', x, y);
+ case 7:
+ __video_putc(' ', x, y);
+ case 6:
+ __video_putc(' ', x, y);
+ case 5:
+ __video_putc(' ', x, y);
+ case 4:
+ __video_putc(' ', x, y);
+ case 3:
+ __video_putc(' ', x, y);
+ case 2:
+ __video_putc(' ', x, y);
+ case 1:
+ __video_putc(' ', x, y);
+ }
+ } else if (c == '\f') {
+ int i;
+ for (i=0;i<lines*cols*2;i+=2) {
+ vidmem[i] = 0;
+ }
+ (*x) = 0;
+ (*y) = 0;
+ } else {
+ vidmem [ ( (*x) + cols * (*y) ) * 2 ] = c;
+ if ( ++(*x) >= cols ) {
+ (*x) = 0;
+ if ( ++(*y) >= lines ) {
+ scroll();
+ (*y)--;
+ }
+ }
+ }
+}
+
+static void video_putc(const char c)
+{
+ int x,y,pos;
+
+ x = orig_x;
+ y = orig_y;
+
+ __video_putc(c, &x, &y);
+
+ orig_x = x;
+ orig_y = y;
+
+ pos = (x + cols * y) * 2; /* Update cursor position */
+ outb_p(14, vidport);
+ outb_p(0xff & (pos >> 9), vidport+1);
+ outb_p(15, vidport);
+ outb_p(0xff & (pos >> 1), vidport+1);
+}
+
+static void video_puts(const char *s)
+{
+ int x,y,pos;
+ char c;
+
+ x = orig_x;
+ y = orig_y;
+
+ while ( ( c = *s++ ) != '\0' ) {
+ __video_putc(c, &x, &y);
+ }
+
+ orig_x = x;
+ orig_y = y;
+
+ pos = (x + cols * y) * 2; /* Update cursor position */
+ outb_p(14, vidport);
+ outb_p(0xff & (pos >> 9), vidport+1);
+ outb_p(15, vidport);
+ outb_p(0xff & (pos >> 1), vidport+1);
+}
+
+int video_init(void)
+{
+ u16 pos;
+
+ static device_t vga_dev;
+ static device_t kbd_dev;
+
+ vidmem = (char *) 0xb8000;
+ vidport = 0x3d4;
+
+ lines = 25;
+ cols = 80;
+
+ outb_p(14, vidport);
+ pos = inb_p(vidport+1);
+ pos <<= 8;
+ outb_p(15, vidport);
+ pos |= inb_p(vidport+1);
+
+ orig_x = pos%cols;
+ orig_y = pos/cols;
+
+#if 0
+ printf("pos %x %d %d\n", pos, orig_x, orig_y);
+#endif
+ if (orig_y > lines) {
+ orig_x = orig_y =0;
+ }
+
+
+ memset(&vga_dev, 0, sizeof(vga_dev));
+ strcpy(vga_dev.name, "vga");
+ vga_dev.ext = 0;
+ vga_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
+ vga_dev.putc = video_putc; /* 'putc' function */
+ vga_dev.puts = video_puts; /* 'puts' function */
+ vga_dev.tstc = NULL; /* 'tstc' function */
+ vga_dev.getc = NULL; /* 'getc' function */
+
+ if (device_register(&vga_dev) == 0) {
+ return 1;
+ }
+
+ if (i8042_kbd_init()) {
+ return 1;
+ }
+
+ memset(&kbd_dev, 0, sizeof(kbd_dev));
+ strcpy(kbd_dev.name, "kbd");
+ kbd_dev.ext = 0;
+ kbd_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
+ kbd_dev.putc = NULL; /* 'putc' function */
+ kbd_dev.puts = NULL; /* 'puts' function */
+ kbd_dev.tstc = i8042_tstc; /* 'tstc' function */
+ kbd_dev.getc = i8042_getc; /* 'getc' function */
+
+ if (device_register(&kbd_dev) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+
+int drv_video_init(void)
+{
+ if (video_bios_init()) {
+ return 1;
+ }
+
+ return video_init();
+}
+
diff --git a/lib_i386/video_bios.c b/lib_i386/video_bios.c
new file mode 100644
index 00000000000..d9709b9e120
--- /dev/null
+++ b/lib_i386/video_bios.c
@@ -0,0 +1,221 @@
+/*
+ * (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>
+
+#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
+
+#ifdef CONFIG_PCI
+
+#ifdef PCI_BIOS_DEBUG
+#define RELOC_16(seg, off) *(u32*)(seg << 4 | (u32)&off)
+extern u32 num_pci_bios_present;
+extern u32 num_pci_bios_find_device;
+extern u32 num_pci_bios_find_class;
+extern u32 num_pci_bios_generate_special_cycle;
+extern u32 num_pci_bios_read_cfg_byte;
+extern u32 num_pci_bios_read_cfg_word;
+extern u32 num_pci_bios_read_cfg_dword;
+extern u32 num_pci_bios_write_cfg_byte;
+extern u32 num_pci_bios_write_cfg_word;
+extern u32 num_pci_bios_write_cfg_dword;
+extern u32 num_pci_bios_get_irq_routing;
+extern u32 num_pci_bios_set_irq;
+extern u32 num_pci_bios_unknown_function;
+
+void print_bios_bios_stat(void)
+{
+ printf("16 bit functions:\n");
+ printf("pci_bios_present: %d\n", RELOC_16(0xf000, num_pci_bios_present));
+ printf("pci_bios_find_device: %d\n", RELOC_16(0xf000, num_pci_bios_find_device));
+ printf("pci_bios_find_class: %d\n", RELOC_16(0xf000, num_pci_bios_find_class));
+ printf("pci_bios_generate_special_cycle: %d\n", RELOC_16(0xf000, num_pci_bios_generate_special_cycle));
+ printf("pci_bios_read_cfg_byte: %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_byte));
+ printf("pci_bios_read_cfg_word: %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_word));
+ printf("pci_bios_read_cfg_dword: %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_dword));
+ printf("pci_bios_write_cfg_byte: %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_byte));
+ printf("pci_bios_write_cfg_word: %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_word));
+ printf("pci_bios_write_cfg_dword: %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_dword));
+ printf("pci_bios_get_irq_routing: %d\n", RELOC_16(0xf000, num_pci_bios_get_irq_routing));
+ printf("pci_bios_set_irq: %d\n", RELOC_16(0xf000, num_pci_bios_set_irq));
+ printf("pci_bios_unknown_function: %d\n", RELOC_16(0xf000, num_pci_bios_unknown_function));
+
+}
+#endif
+
+#define PCI_CLASS_VIDEO 3
+#define PCI_CLASS_VIDEO_STD 0
+#define PCI_CLASS_VIDEO_PROG_IF_VGA 0
+
+
+static u32 probe_pci_video(void)
+{
+ pci_dev_t devbusfn;
+
+ if ((devbusfn = pci_find_class(PCI_CLASS_VIDEO,
+ PCI_CLASS_VIDEO_STD,
+ PCI_CLASS_VIDEO_PROG_IF_VGA, 0)) != -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, 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 */
+ if (pci_enable_legacy_video_ports(pci_bus_to_hose(PCI_BUS(devbusfn)))) {
+ 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;
+}
+
+
+#endif
+
+static int probe_isa_video(void)
+{
+ u32 ptr;
+ char *buf;
+
+ if (0 == (ptr = isa_map_rom(0xc0000, 0x8000))) {
+ return -1;
+ }
+ if (NULL == (buf=malloc(0x8000))) {
+ 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;
+
+ /* clear the video bios area in case we warmbooted */
+ memset((void*)0xc0000, 0, 0x8000);
+ memset(&regs, 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) {
+ int size;
+ int i;
+ u8 sum;
+
+ PRINTF("Found video bios signature\n");
+ size = 512*readb(0xc0002);
+ 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, &regs, &regs);
+ PRINTF("INT 0x10 vector after: %04x:%04x\n",
+ readw(0x42), readw(0x40));
+ PRINTF("BIOS returned %scarry\n", regs.eflags & 1?"":"NOT ");
+#ifdef PCI_BIOS_DEBUG
+ print_bios_bios_stat();
+#endif
+ return (regs.eflags & 1);
+
+ }
+
+ return 1;
+
+}
+
+
diff --git a/lib_i386/zimage.c b/lib_i386/zimage.c
index 190d46ef749..9d33b2d2727 100644
--- a/lib_i386/zimage.c
+++ b/lib_i386/zimage.c
@@ -220,8 +220,8 @@ void boot_zimage(void *setup_base)
memset(&regs, 0, sizeof(struct pt_regs));
regs.xds = (u32)setup_base >> 4;
- regs.xss = 0x8e00;
- regs.esp = 0x200;
+ regs.xss = 0x9000;
+ regs.esp = 0x9000;
regs.eflags = 0;
enter_realmode(((u32)setup_base+SETUP_START_OFFSET)>>4, 0, &regs, &regs);
}