This now works enough to load linuxbios and jump to it!

This commit is contained in:
Ronald G. Minnich 2001-06-04 20:50:27 +00:00
parent 42e38b5a3e
commit 9c56e39fcf

View file

@ -1,6 +1,6 @@
#include <asm.h>
#include <cpu/p5/macros.h>
#include <intel.h>
#include "asm.h"
//#include <cpu/p5/macros.h>
#include "intel.h"
/*
*/
@ -9,29 +9,16 @@
#define SPL_RAM_SEG 0x8000
#define DOC_SPL_START_BLK 2 /* 0,1 for IPL */
#define DOC_SPL_SIZE_IN_PAGE 126 /* 1 page = 512 bytes, total 63kB */
#define DOC_SPL_SIZE_IN_PAGE 252 /* 1 page = 512 bytes, total 63kB */
/* wow, the usual way to to this hurts. So we do it our way:
* 32-bit test not needed.
*/
/*#include <cpu/p5/start32.inc>*/
.org 0xfe000
.org 0x0
.code16
_start: jmp _realstart
gdt: //GDT entry 0 (null segment)
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
// GDT 1
.word 0xffff, 0x0000 /* flat code segment */
.byte 0x0, 0x9a, 0xcf, 0x0
.word 0xffff, 0x0000 /* flat data segment */
.byte 0x0, 0x92, 0xcf, 0x0
gdtptr:
.word 4*8-1
.long gdt /* we know the offset */
.long 0
/* initialize registers */
#define REG(a) a&0xfc, (a&0x3)|4
@ -62,106 +49,57 @@ register_table:
.byte REG(0x6c), 0x0
.byte 0x0
_realstart:
// movb $0xaa,%al
// outb %al,$0x80
cli
movw %cs, %ax
movw %ax, %es
.byte 0x66 /* prefix */
.byte 0x26
.byte 0x0f, 0x01, 0x16 /* lgdt [es:offset]*/
.word gdtptr - EXT(_start) /* offset in segment */
movl %cr0, %eax
andl $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */
orl $0x60000001, %eax /* CD, NW, PE = 1 */
movl %eax, %cr0
/* invalidate the cache */
invd
data32 ljmp $0x10, $.Lprotected
.Lprotected:
.code32
movw $0x18, %bx
movw %bx, %es
movw %bx, %ds
/*
movw %bx, %es
movw %bx, %fs
movw %bx, %gs
movw %bx, %ss
*/
// Registers
// %esp holds the 0x80000000 pattern
// %edx always hold $0xcf8
// %esi holds 0
// %edi holds 0x40000000
// %bl is reused as needed.
// store this constant in %esp
movl $0x80000000, %esp
/* make the flash writeable */
/* select the south bridge, register 40 (base) */
/* south bridge is device 7. 7 << 3 is 0x38 */
movl %esp, %eax
#define FLASHREG ((SUPERIO_DEVFN<<8) | 0x40)
orw $FLASHREG, %ax
mov $0xcf8,%dx
outl %eax,%dx
#if (SUPERIO_DEVFN == 0x88)
mov $0xfc,%dl
inl %dx,%eax
/*
For 8231:
Please see databook revision 1.2, November 13, 2000. Page68.
PCI to ISA bridge: Regx40[4]=1, Regx41[0-6]=1.
*/
orw $0x7f10, %ax
outl %eax,%dx
#endif
#if (SUPERIO_DEVFN == 0x38)
Please see databook revision 1.33, January 7, 2000. Page55
and 56.
PCI to ISA bridge: Regx40[0]=1 (write enable)
Regx43[0-7]=1(all bits set to 1)
/* but 0x01 makes flash writeable. You need this for DoC */
mov $0x0cfc,%dx
inl %dx,%eax
orl $0xc0000001, %eax
outl %eax,%dx
#endif
movw %ax, %ds
movl $0x80008840, %eax
movw $0x0cf8, %dx
outl %eax,%dx
movb $0xfc,%dl
movb $0x54,%al
outb %al,%dx
// inl %dx, %eax
// orw $0x7f10, %ax
// outw %ax,%dx
//.code32
#define loop200 $0x5000
#define loop100 $0x2500
movl $0x80000000,%esp
ram_set_registers:
movl $register_table, %esi
movw $register_table, %si
cld
1:
movl %esp, %eax
orb (%esi), %al
orb (%si), %al
testb %al, %al
jz done_ram_set_registers
andb $0xf8, %dl
outl %eax, %dx
inc %esi
orb (%esi), %dl
inc %esi
movb (%esi), %al
inc %si
orb (%si), %dl
inc %si
movb (%si), %al
outb %al, %dx
// PCI_WRITE_CONFIG_BYTE
inc %esi
inc %si
jmp 1b
// movb $0xbb,%al
// outb %al,$0x80
done_ram_set_registers:
xorl %esi, %esi
movl $0x4000000, %edi
xorw %si, %si
// movl $0x4000000, %edi
/* begin to initialize*/
// I forget why we need this, but we do
mov $0xa55a5aa5, %ecx
mov %ecx, (%esi)
mov %ecx, (%edi)
movl $0xa55a5aa5, %ecx
movl %ecx, (%si)
// mov %ecx, (%edi)
// REMEMBER: 0xcf8 was set to 0x8000006c above. No need to set
// again!
// Also, remember: %edx has 0xcfc from the above loop!
@ -172,16 +110,16 @@ done_ram_set_registers:
/* wait 200us*/
// You need to do the memory reference. That causes the nop cycle.
mov (%esi), %ecx
mov (%edi), %ecx
movw (%si), %cx
// mov (%edi), %ecx
DELAY(loop200)
/* set precharge */
WRITE_6c($0x6C, $0x02)
/* dummy reads*/
mov (%esi), %ecx
mov (%edi), %ecx
movw (%si), %cx
// mov (%edi), %ecx
/* set CBR*/
WRITE_6c($0x6C, $0x04)
@ -190,8 +128,8 @@ done_ram_set_registers:
movb $8, %bl
eightreads:
mov (%esi), %ecx
mov (%edi), %ecx
movw (%si), %cx
// mov (%edi), %ecx
DELAY(loop100)
dec %bl
cmpb $0, %bl
@ -201,17 +139,17 @@ eightreads:
// 0x150 is cas2. We are now using 0x1d0, which is cas3
WRITE_6c($0x6c, $0x03)
movl $0x1d0, %ecx
movl (%ecx), %ecx
movl $0x40001d0, %ecx
movl (%ecx), %ecx
movw $0x1d0, %di
movl (%di), %ecx
// movl $0x40001d0, %ecx
// movl (%ecx), %ecx
/* set to normal mode */
WRITE_6c($0x6C, $0x00)
movl $0x55aa55aa, %ecx
mov %ecx, (%esi)
mov (%esi), %ecx
movl %ecx, (%si)
movl (%si), %ecx
// Set the refresh rate.
movb $0x68, %al
@ -226,7 +164,9 @@ eightreads:
movb $1, %al
outb %al, %dx
//CS_WRITE($0x6B, $0x01)
// movb $0xcc,%al
// outb %al,$0x80
/* now for flash ... */
/* NOTE: MUST NOT DESTROY %ecx! */
/* INPUT: %al, the register. %ecx, the write data */
@ -261,105 +201,145 @@ eightreads:
*
* $Id$
*/
// .code16
#define DOC_WIN_SEG 0xfe00
#define DOC_STACK 0x04000
#define SPL_RAM 0x80000
#define DOC_SPL_START_BLK 2 /* 0,1 for IPL */
#define DOC_SPL_SIZE_IN_PAGE 126 /* 1 page = 512 bytes, total 63kB */
#define DOC_SPL_SIZE_IN_PAGE 252 /* 1 page = 512 bytes, total 63kB */
ipl_start:
#if 0
//#if 0
/* stack and es already set. */
/* O.K. we have DRAM now, so set up STACK for CALL/RET */
movw $DOC_STACK_SEG, %ax
movw %ax, %ss
movw $SPL_RAM_SEG, %ax
movw %ax, %es
movl $DOC_STACK_SEG, %esp # set %sp
#endif
// movl $DOC_STACK_SEG, %esp # set %sp
//#endif
/* NOTE: in ollie's original code, %ds was at 0xfe00, i.e.
* 0xfe000, i.e. base of DoC. We have to adjust for that when
* we set %edi and %esi
*/
movl $DOC_STACK, %esp # set %sp
movl $SPL_RAM, %edx # start of RAM
xorl %ecx, %ecx # clear %ecx
movl $0xfe800, %esi # point %si to CDSN Data area
movl $0xff000, %edi # point %di to CDSN Control area
movl $DOC_SPL_START_BLK, %ebp # start page of LinuxBIOS
movb $0x84, %al # Reset DOC Millennium
call doc_reset
movb $0x85, %al # Turn into Normal Mode
call doc_reset
// movl $0x80008840,%eax
// mov $0xcf8,%dx
// outl %eax,%dx
// mov $0xfc,%dl
// inl %dx,%eax
movb $0xbb, %al
outb %al,$0x80
xorw %sp,%sp
xorw %dx,%dx
// movl $DOC_STACK, %esp # set %sp
// movl $SPL_RAM, %edx # start of RAM
// xorl %ecx, %ecx # clear %ecx
movw $0x800, %si # point %si to CDSN Data area
movw $0x1000,%di # point %di to CDSN Control area
movw $DOC_SPL_START_BLK, %bp # start page of LinuxBIOS
movb $0x0, %ds:0x03(%di)
movb $0x84,%ds:0x02(%di)
movb $0x84,%ds:0x02(%di)
call delay4nop
movb $0x85,%ds:0x02(%di)
movb $0x85,%ds:0x02(%di)
call delay4nop
read_next_page:
movl $0xff000, %edi # point %di to CDSN Control area
movw $0x1000, %di # point %di to CDSN Control area
movw $0x800, %si
flash_command:
movb $0x03, 0x04(%edi) # start command cycle
movb $0x00, (%esi) # issue flash command Read00
call doc_cycle_end
movb $0x13, %ds:0x04(%di) # start command cycle
call delay4nop
movb $0x00, %ds:(%si) # issue flash command Read00
movb $0x00, %ds:0x1e(%di)
movb $0x11, %ds:0x04(%di)
movw %bp, %bx # %bp is current page number
flash_address:
shll $0x08, %ebx
movb $0x03, %cl # this one is DANGEROUS but I am
# sure the upper 3 bytes == 0x00
movw $0x03, %cx # this one is DANGEROUS but I am
movb $0x05, 0x04(%edi) # start address cycle
movb $0x15, %ds:0x04(%di) # start address cycle
call delay4nop
0:
movb %bl, (%esi) # write address to CDSNIO
movb %bl, %ds:(%si) # write address to CDSNIO
shrw $0x08, %bx # shift next address byte
loop 0b
call doc_cycle_end
movb $0x00, %ds:0x1e(%di)
movb $0x31, %ds:0x04(%di)
// call doc_cycle_end
call delay4nop
wait_for_flash_ready:
/* delay by reding NOP register before polling the FLASH READY bit,
this is inlined to save a call/ret pair */
doc_delay:
movb $0x04, %cl # this one is DANGEROUS but I am
movb %ds:0x04(%di),%ah
movw $0x04, %cx # this one is DANGEROUS but I am
# sure the upper 3 bytes == 0x00
0:
movb 0x20(%edi), %al # read DOC NOP retisger
movb %ds:0x20(%di), %al # read DOC NOP retisger
loop 0b # four times
testb $0x80, 0x04(%edi) # is flash ready ?
testb $0x80,%ah # is flash ready ?
jz wait_for_flash_ready
movb 0x1d(%edi), %al # init read pipeline
movw $0x100, %cx # 1 page = 512 bytes
movl $0xfe800, %esi # point %si to CDSN Data area
movl %edx, %edi # restore saved current destination
rep
movsw
movl %edi, %edx # save current destination
movb %ds:0x1d(%di), %al # init read pipeline
movw $0x1ff, %cx # 1 page = 512 bytes
movw $0x800, %si # point %si to CDSN Data area
movw %dx, %di # restore saved current destination
rep movsb
movw $0x101f,%si
movsb
// call dely4nop
movw %di, %dx # save current destination
mov %bp,%di
sub $128,%di
shl $9,%di
movb %es:(%di),%al
out %al,$0x80
// DELAY(loop200)
// DELAY(loop200)
// mov $0xffff,%cx
//aa: loop aa
inc %di
movb %es:(%di),%al
out %al,$0x80
incw %bp # increse current page number
cmpw $128, %bp # moved 63 KB ??
jl read_next_page # no, read next page
sis630ipl_end:
# jmp to 8000:0000, where SPL
# (LinuxBIOS) starts in RAM
# ljmp $0x10,$0x8000
movb $0xdd, %al
outb %al,$0x80
jmp spl_vector
doc_reset:
delay4nop:
movb %ds:0x20(%di),%al
movb %ds:0x20(%di),%al
movb %ds:0x20(%di),%al
movb %ds:0x20(%di),%al
ret
//doc_reset:
/* Input: AL = value write to DOC_CONTROL register
Clobberd: CX */
movb %al, 0x02(%edi) # write DoC Control retister
movb %al, 0x02(%edi) # twice
ret # End of doc_reset
// movb %al, 0x02(%edi) # write DoC Control retister
// movb %al, 0x02(%edi) # twice
// ret # End of doc_reset
doc_cycle_end:
movb $0x00, 0x1e(%edi) # flush write pepeline
movb $0x01, 0x04(%edi) # end command cycle
ret
//doc_cycle_end:
// movb $0x00, 0x1e(%di) # flush write pepeline
// movb $0x31, 0x04(%di) # end command cycle
// ret
/* we don't need these. We only do I/O to MCR 0 */
@ -388,14 +368,18 @@ pci_read_dword:
RETSP
#endif
.org 0xfe1f0
.org 0x01f0
reset_vector:
.byte 0xea #jump to fe00:0000, where IPL
.word 0x0000, DOC_WIN_SEG #starts in DoC
.code32
spl_vector:
invd
jmpl $0x10, $0x80000
// invd
// movb $0xdd,%al
// outb %al,$0x80
// jmpl $0x10, $0x80000
.byte 0xea
.word 0x0000, 0x8000
# jumpl $0x80000
# put this here to buy some room
pad: .byte 0,0
pad: .byte 0,0,0,0,0,0