The attached code seems to work fine when singel stepping in Bochs
(http://www.bochs.com/) but not in real life :-) I think I'm close, but no cigar, yet.
Anyone else working on this wanting to collaborate?
------------------code---------------
//#define BOCHS_TEST
.org 0xf100
SC400RegInit:
dw 0xAB00 ;Configure 2 banks of DRAM:32 bit, EDO, 2mb depth
dw 0xAB01
dw 0x5C04 ;Set DRAM timing as slow as possible
dw 0x4005 ;Enable refresh, use 32khz osc for refresh
;dw 0x0921 ;Enable E000 seg for linear decode, disable 3ff0000 boot
vector
;db 0x21, %0001101 ;E000 och C000.
;db 0x21, %0001111 ;E000, D000 och C000.
db 0x21, %0001000 ;Neither E000, D000 or C000.
dw 0x0724 ;waitstates needed?
db 0x32, %00000000 ; bit22-15 for MMSA, actually default.
db 0x33, %00001000 ; MMSA enabled, ROMCS0, !WP, !Cache
;Required for superio interface. SuperIO needed to control LEDs.
dw 0x1938 ;Select ISA iochrdy, IOCS16, and AEN signals Vs. GPIOs
dw 0x0480 ;cpu clk:high spd mode=33mhz, low spd mode = 8 mhz
;required for remote debug via serial port
dw 0x01D1 ;Enable internal UART at 3f8
;Only required for UART remote debug if interrupt driven mode enabled
dw 0x40D8 ;Internal UART uses IRQ4
SC400RegTableLen = (* - SC400RegInit) / 2
;============< ElanSC400 Board Superio Initialization Constants >===========
SC400BoardSuperIO_Reg_Initial_Values:
db 0x00, %11111111, %01001010 ; Enable UART, FDC, IDE
db 0x01, %11001100, %00001100 ; Set uart 1 to base 2E8
db 0x05, %11111111, %00000101 ; Enable keyboard, disable RTC
db 0x0A, %11111111, 0x80 ; CS 0 address low
db 0x10, %11111111, 0x06 ; CS 0 address high
db 0x0B, %10111000, 0x90 ; CS 0 enable
db 0x0C, %11111111, 0x80 ; CS 1 address low
db 0x11, %11111111, 0x00 ; CS 1 address high
db 0x0D, %00111000, 0x90 ; CS 1 enable
SC400BoardNum_SuperIO_Initial_Values EQU (* - SC400BoardSuperIO_Reg_Initial_Values) / 3
;================= < ElanSC400 Chip And Eval Board Init Code >===============
.org 0xf200
power_onA:
cli
cld
mov ax, cs
mov ds, ax
;----------< Blast out the basic init for the ElanSC400 >-----------
;mov si, offset SC400RegInit
mov si, #SC400RegInit
mov cx, #SC400RegTableLen
mov dx, #0x22
db 0x2e ;Do the outSW from CS. DS is not set up yet
rep
outsw
;------< SC400 Eval Board National 306 Superio "Detection" >-------
mov dx, #0x398 ;Superio index register on the ElanSC400 eval board
;The 1st 2 reads of the index register after POR give 88H followed
;by 0H. This is the ID mechanism. Consume these bytes, but dont
;rely on their presence, shutdown is not a cold reset!
in al, dx
in al, dx
;mov si, offset SC400BoardSuperIO_Reg_Initial_Values
mov si, #SC400BoardSuperIO_Reg_Initial_Values
mov cx, #SC400BoardNum_SuperIO_Initial_Values
Output_Super:
;cs:
mov ax, [si] ; get index into 306s indexed regs
; and mask to AH
out dx, al ; Output index
inc dx
in al, dx
not ah ; Get save mask
and al, ah
not ah ; Get replace mask
;cs:
and ah, [si+2]
add si, #3
or al, ah
out dx, al ; Must do twice for SuperIO
out dx, al
dec dx
loop Output_Super
;============< Operations Required For Either SC300 Or SC400 >===============
;-----------------< RTC Oscillator Initialization >------------------
; Set up the RTC oscillator divide chain as soon as possible, because
; the output can take from 2 to 7 seconds to stabilize. Note that the
; ElanSC400s internal graphics controller uses clocks from the RTc
; core, and will not work unless the RTC oscillator is running.
mov al, #(0x0A + 0x80)
out #0x70, al
in al, #0x71
and al, #0x8F ;1000 1111b ;mask off divider bits
or al, #0x20 ;0010 0000b ;or in divider enable bit
out #0x71, al ;enable the oscillator
;-< Flash Onboard (for SC400) or Port 80h Card Based (for SC300) LEDs >-
;This is just a bit of code to visually detect that the pdrem remote
;debug kernel is indeed getting control at reset. It flashes the LEDs
;on a port 80H card. The test is designed such that if the stack is
;not working (like the wrt line isnt hooked up from the eval board to
;the PromIce) the LEDs flash forever.
;---------------------------------------------------------------------
mov ax, #0x02000 ;Init a debugger stack in normal DRAM
mov ss, ax
mov ax, #0x1800 ; stack...
mov sp, ax
;FLASHES THE PORT 80H LEDS
mov cx, #0x02
Flash_P80:
mov al, #0x044
; mov al, #0x0AA
out #0x80, al
push cx
mov cx, #0x02000
loop *
pop cx
not al
out #0x80,al
push cx
mov cx, #0x02000
loop *
pop cx
loop Flash_P80
#ifdef BOCHS_TEST
mov ax, #0xE000
#else //SC400 ev. board
mov ax, #0xB000
#endif
mov ds, ax
//Move setup
//Someone claimed setup to be at 0x90000 but I thinks it belongs at 0x90200?
mov ax, #0x9020
mov es, ax
xor di, di
mov si, #512
//Someone claimed setup to be 0x800 (2K) but I thinks it's actually 0x1200
bytes?
mov cx, #(0x1200/2)
rep
movsw
//Move system
#ifdef BOCHS_TEST
mov cx, #((0xFFF0 - 0x1200)/2) //Does'nt move all of it, just testing.
mov ax, #0x1000
mov es, ax
xor di, di
rep
movsw
#else //SC400 ev. board
mov cx, #((0x8000 - 0x1200)/2) ;Ca.
mov ax, #0x1000
mov es, ax
xor di, di
rep
movsw
// Display what was moved
seg es
mov ax, [0]
mov dx, #0x680
out dx, al
mov al, ah
out #0x80, al
xor cx, cx
loop *
//bl is MSSA addr.
mov bl, #1
MMSA_move_loop:
mov al, #0x32
out #0x22, al
mov al, bl
out #0x23, al
mov ax, es
shr di, #4
add ax, di
mov es, ax
xor di, di
xor si, si
mov cx, #(0x8000 / 2)
rep
movsw
// Visa vad som flyttades
seg es
mov ax, [0]
mov dx, #0x680
out dx, al
mov al, ah
out #0x80, al
xor cx, cx
loop *
add bl, #1
cmp bl, #12
jnz MMSA_move_loop
#endif
xor cx, cx
loop *
loop *
loop *
//Code borrowed from bochs-bios setup
mov ax, #0xfffe
mov sp, ax
mov ax, #0x0000
mov ds, ax
mov ss, ax
;; zero out BIOS data area (40:00..40:ff)
mov es, ax
mov cx, #0x0080 ;; 128 words
mov di, #0x0400
cld
rep
stosw
mov AL, #0x04 ;0x80 code
out 0x80, AL
;; set all interrupts to default handler
mov bx, #0x0000 ;; offset index
mov cx, #0x0100 ;; counter (256 interrupts)
mov ax, #dummy_iret_handler
mov dx, #0xF000
MYpost_default_ints:
mov [bx], ax
inc bx
inc bx
mov [bx], dx
inc bx
inc bx
loop MYpost_default_ints
;; base memory in K 40:13 (word)
mov ax, #BASE_MEM_IN_K
mov 0x0413, ax
//Jump to setup
JMP_AP(0x9020, 0)
.org 0xfff0 ; Power-up Entry Point
JMP_AP(0xf000, power_onA)