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