559 lines
10 KiB
NASM
559 lines
10 KiB
NASM
; SCCSID = @(#)uf.bios1.asm 1.16 7/3/95
|
|
; Author: J. Box, Jerry Kramskoy
|
|
;
|
|
; Purpose:
|
|
; provides Intel BIOS for the following:
|
|
; RTC interrupt
|
|
; fixed disk (on dual card)
|
|
;
|
|
|
|
; C-services (through 'bop' instruction)
|
|
BIOS_UNEXP_INT = 2
|
|
BIOS_RTC_INT = 70h
|
|
BIOS_REDIRECT_INT = 71h
|
|
BIOS_D11_INT = 72h
|
|
BIOS_X287_INT = 75h
|
|
BIOS_DISK_IO = 13h
|
|
BIOS_MOUSE_INT1 = 0BAh
|
|
BIOS_MOUSE_INT2 = 0BBh
|
|
BIOS_MOUSE_IO_LANGUAGE = 0BCh
|
|
BIOS_MOUSE_IO_INTERRUPT = 0BDh
|
|
BIOS_MOUSE_VIDEO_IO = 0BEh
|
|
BIOS_CPU_RETURN = 0feh
|
|
BIOS_IRET_HOOK = 52h
|
|
|
|
; ICA registers
|
|
ICA_MASTER_CMD = 020h
|
|
ICA_MASTER_IMR = 021h
|
|
ICA_SLAVE_CMD = 0A0h
|
|
ICA_SLAVE_IMR = 0A1h
|
|
; and commands
|
|
ICA_EOI = 020h
|
|
|
|
; CMOS registers
|
|
CMOS_addr = 070h
|
|
CMOS_data = 071h
|
|
NMI_DISABLE = 080h
|
|
CMOS_StatusA = NMI_DISABLE + 0Ah
|
|
CMOS_StatusB = NMI_DISABLE + 0Bh
|
|
CMOS_StatusC = NMI_DISABLE + 0Ch
|
|
CMOS_Shutdown = 0Fh
|
|
; CMOS constants (bits in StatusB or StatusC)
|
|
CMOS_PI = 01000000b ; Periodic interrupt
|
|
CMOS_AI = 00100000b ; Alarm interrupt
|
|
; microseconds at 1024Hz
|
|
CMOS_PERIOD_USECS = 976
|
|
|
|
|
|
include bebop.inc
|
|
|
|
; DUE TO LIMITATIONS IN EXE2BIN, we define
|
|
; the region 0 - 0xdfff (segment 0xf000) in this file
|
|
; and the region 0xe000 - 0xffff in file 'bios2.asm'
|
|
;
|
|
; each file should be SEPARATELY put through
|
|
; MASM,LINK, and EXE2BIN to produce 2 binary image files
|
|
; which get loaded into the appropriate regions during
|
|
; SoftPC startup.
|
|
|
|
|
|
;------------------------;
|
|
; bios data area ;
|
|
;------------------------;
|
|
; BIOS variables area
|
|
BIOS_VAR_SEGMENT SEGMENT at 40h
|
|
|
|
|
|
ORG 098h
|
|
rtc_user_flag DD ? ; 98
|
|
rtc_micro_secs DD ? ; 9c
|
|
rtc_wait_flag DB ? ; a0
|
|
|
|
ORG 8eh
|
|
hf_int_flag db ? ; 8e
|
|
|
|
BIOS_VAR_SEGMENT ENDS
|
|
|
|
|
|
code segment
|
|
|
|
assume cs:code, ds:BIOS_VAR_SEGMENT
|
|
|
|
;----------------------------------------------------;
|
|
; D11 ;
|
|
; services unused interrupt vectors ;
|
|
; ;
|
|
;----------------------------------------------------;
|
|
ORG 01BE0h
|
|
D11: bop BIOS_D11_INT
|
|
iret
|
|
|
|
;----------------------------------------------------;
|
|
; IRET HOOK ;
|
|
; Return control to the monitor after an ISR ;
|
|
; returns to here. ;
|
|
;----------------------------------------------------;
|
|
|
|
ORG 01C00h
|
|
bop BIOS_IRET_HOOK
|
|
iret
|
|
|
|
;----------------------------------------------------;
|
|
; re_direct ;
|
|
; This routine fields level 9 interrupts ;
|
|
; control is passed to Master int level 2 ;
|
|
;----------------------------------------------------;
|
|
ORG 01C2Fh
|
|
re_direct: bop BIOS_REDIRECT_INT
|
|
int 0ah
|
|
iret
|
|
|
|
;----------------------------------------------------;
|
|
; int_287 ;
|
|
; service X287 interrupts ;
|
|
; ;
|
|
;----------------------------------------------------;
|
|
ORG 01C38h
|
|
int_287: bop BIOS_X287_INT
|
|
int 02
|
|
iret
|
|
|
|
|
|
;----------------------------------------------------;
|
|
; rtc_int ;
|
|
; rtc interrupt handler ;
|
|
;----------------------------------------------------;
|
|
ORG 04B1Bh
|
|
|
|
rtc_int: push ax
|
|
push ds
|
|
mov ax, BIOS_VAR_SEGMENT
|
|
mov ds, ax
|
|
|
|
rtc_test_pending:
|
|
|
|
;; Check for pending interrupt
|
|
|
|
mov al, CMOS_StatusC
|
|
out CMOS_addr, al
|
|
in al, CMOS_data ; reads then clears pending interrupts
|
|
|
|
;; Mask with enabled interrupts
|
|
|
|
mov ah, al ; save pending interrupts
|
|
mov al, CMOS_StatusB
|
|
out CMOS_addr, al
|
|
in al, CMOS_data
|
|
and ah, al
|
|
|
|
;; Test pending, enabled interrupts (in ah) for work to do
|
|
|
|
test ah, (CMOS_PI+CMOS_AI)
|
|
jnz rtc_test_enabled
|
|
|
|
;; Deselecting the cmos
|
|
|
|
mov al, CMOS_Shutdown
|
|
out CMOS_addr, al
|
|
|
|
;; Send eoi to ICA
|
|
|
|
mov al, ICA_EOI
|
|
out ICA_SLAVE_CMD, al
|
|
out ICA_MASTER_CMD, al
|
|
|
|
;; And return
|
|
|
|
pop ds
|
|
pop ax
|
|
iret
|
|
|
|
rtc_test_enabled:
|
|
|
|
;; Test for periodic interrupt triggered
|
|
|
|
test ah, CMOS_PI
|
|
jz rtc_test_alarm
|
|
|
|
;; Decrement the microsecond count
|
|
|
|
.386
|
|
sub ds:[rtc_micro_secs], CMOS_PERIOD_USECS
|
|
.286
|
|
jnc rtc_test_alarm
|
|
|
|
;; Disable PI interrupt in CMOS if count expired
|
|
|
|
mov al, CMOS_StatusB
|
|
out CMOS_addr, al
|
|
in al, CMOS_data
|
|
and al, 10111111b ; Disable PI interrupt
|
|
out CMOS_data, al
|
|
|
|
;; Update the flag byte to say time has expired
|
|
|
|
push es
|
|
push bx
|
|
les bx, rtc_user_flag
|
|
or byte ptr es:[bx], 080h
|
|
pop bx
|
|
pop es
|
|
|
|
;; Mark timer-in-use flag in-active
|
|
|
|
and rtc_wait_flag, 0feh; Show wait is not active
|
|
|
|
rtc_test_alarm:
|
|
|
|
;; Test for alarm interrupt triggered
|
|
|
|
test ah, CMOS_AI
|
|
jz rtc_test_pending
|
|
|
|
;; Call users alarm function (first deselecting the cmos)
|
|
|
|
mov al, CMOS_Shutdown
|
|
out CMOS_addr, al
|
|
int 04Ah
|
|
|
|
;; Repeat in case a new interrupt occurred
|
|
|
|
jmp rtc_test_pending
|
|
|
|
|
|
|
|
;----------------------------------------------------;
|
|
; disk_io
|
|
; route to disk/diskette i/o service ;
|
|
;----------------------------------------------------;
|
|
org 2e86h ;(must match DISKO_OFFSET in diskbios.c)
|
|
|
|
disk_io proc far
|
|
; is this request for fixed disk or diskette?
|
|
cmp dl,80h
|
|
jae p0
|
|
|
|
; for diskette.
|
|
int 40h
|
|
bye:
|
|
retf 2
|
|
p0:
|
|
sti
|
|
; reset? (ah = 0). reset diskette also
|
|
or ah,ah
|
|
jnz p1
|
|
int 40h
|
|
sub ah,ah
|
|
cmp dl,81h
|
|
ja bye
|
|
|
|
p1:
|
|
; carry out the disk service requested from 'C'.
|
|
; those requests which expect to cause a
|
|
; disk interrupt will 'call' wait below,
|
|
; which returns back to 'C'. Eventually
|
|
; 'C' returns after the bop.
|
|
|
|
push ds
|
|
bop BIOS_DISK_IO
|
|
pop ds
|
|
retf 2
|
|
|
|
disk_io endp
|
|
|
|
;----------------------------------------------------;
|
|
; wait ;
|
|
; wait for disk interrupt ;
|
|
; ('called' from waitint() in diskbios.c ;
|
|
;----------------------------------------------------;
|
|
org 329fh ;(must match DISKWAIT_OFFSET in diskbios.c)
|
|
wate proc
|
|
|
|
sti
|
|
clc
|
|
mov ax,9000h
|
|
int 15h
|
|
push ds
|
|
push cx
|
|
mov ax, 40h
|
|
mov ds, ax
|
|
xor cx, cx
|
|
not_yet: cmp byte ptr ds:[8eh], 0
|
|
loopz not_yet
|
|
pop cx
|
|
pop ds
|
|
bop BIOS_CPU_RETURN
|
|
wate endp
|
|
|
|
;----------------------------------------------------;
|
|
; hd_int ;
|
|
; field fixed disk controller's interrupt ;
|
|
;----------------------------------------------------;
|
|
org 33b7h ; (must match DISKISR_OFFSET in diskbios.c)
|
|
|
|
hd_int proc near
|
|
push ds
|
|
mov ax,BIOS_VAR_SEGMENT
|
|
mov ds,ax
|
|
; inform everybody that a fixed disk interrupt
|
|
; occurred
|
|
mov hf_int_flag,0ffh
|
|
|
|
; clear down the interrupt with the ica's
|
|
|
|
mov al, ICA_EOI
|
|
out ICA_SLAVE_CMD, al
|
|
out ICA_MASTER_CMD, al
|
|
|
|
sti
|
|
mov ax,9100h
|
|
int 15h
|
|
pop ds
|
|
iret
|
|
|
|
hd_int endp
|
|
|
|
; read bytes 0 - 3fff in from binary image
|
|
; when accessing bios1.rom.
|
|
; if need more than this, change value here
|
|
; to 'n' and in sas_init(), change read of bios1.rom
|
|
; to have transfer count of 'n'+1
|
|
|
|
org 3fffh
|
|
insignia_endmark db 0
|
|
|
|
ifdef SUN_VA
|
|
;
|
|
; NB. the following addresses are allocated to SUN for DOS Windows 3.0.
|
|
; They are not to be used by anyone else.
|
|
; THIS AREA IS SUN PROPERTY - TRESPASSERS WILL BE PROSECUTED
|
|
; However please note that only the ranges below are reserved.
|
|
;
|
|
ORG 04000h
|
|
sunroms_2 LABEL FAR
|
|
db 512 dup (0) ; reserved
|
|
ORG 05000h
|
|
sunroms_3 LABEL FAR
|
|
db 512 dup (0) ; reserved
|
|
endif
|
|
|
|
ORG 06000h
|
|
|
|
; this is a fake IFS header to make DOS 4.01
|
|
; happy with HFX. Do not move/alter.
|
|
hfx_ifs_hdr LABEL FAR
|
|
DB 0ffh, 0ffh, 0ffh, 0ffh
|
|
DB "HFXREDIR"
|
|
DB 00h, 02ch
|
|
DB 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h
|
|
|
|
ifndef GISP_SVGA
|
|
|
|
ORG 06020h
|
|
ifndef SUN_VA
|
|
write_teletype proc far
|
|
retf
|
|
write_teletype endp
|
|
|
|
else
|
|
|
|
write_teletype proc far
|
|
push ds
|
|
push si
|
|
mov si, 0f000h
|
|
mov ds, si
|
|
mov si, 06400h
|
|
push ax
|
|
mov ah, 0eh
|
|
push bp
|
|
mov bp, 2
|
|
push dx
|
|
push bx
|
|
mov bx, 0
|
|
|
|
start_write:
|
|
cmp bp, [si]
|
|
je finish_write
|
|
mov al, ds:[bp+si]
|
|
inc bp
|
|
int 010h
|
|
jmp start_write
|
|
|
|
finish_write:
|
|
mov word ptr [si], 2
|
|
pop bx
|
|
pop dx
|
|
pop bp
|
|
pop ax
|
|
pop si
|
|
pop ds
|
|
retf
|
|
write_teletype endp
|
|
|
|
ORG 06200h
|
|
; mouse_io_interrupt
|
|
mouse_io:
|
|
JMP hopover
|
|
BOP BIOS_MOUSE_IO_LANGUAGE
|
|
RETF 8
|
|
hopover:
|
|
BOP BIOS_MOUSE_IO_INTERRUPT
|
|
IRET
|
|
|
|
|
|
ORG 06220h
|
|
; mouse_int1
|
|
mouse_int1:
|
|
BOP BIOS_MOUSE_INT1
|
|
IRET
|
|
|
|
ORG 06240h
|
|
; mouse_video_io
|
|
mouse_video_io:
|
|
BOP BIOS_MOUSE_VIDEO_IO
|
|
IRET
|
|
|
|
ORG 06260h
|
|
; mouse_int2
|
|
mouse_int2:
|
|
BOP BIOS_MOUSE_INT2
|
|
IRET
|
|
|
|
ORG 06280h
|
|
; mouse_version
|
|
mouse_version: ; dummy, for compatibility
|
|
DB 042h,042h,00h,00h
|
|
|
|
ORG 062a0h
|
|
; mouse_copyright
|
|
mouse_copyright: ; dummy, for compatibility
|
|
DB "Copyright 1987-91 Insignia Solutions Inc"
|
|
|
|
ORG 06400h
|
|
; scratch pad area - this is where the messages go!
|
|
|
|
endif
|
|
|
|
endif ; GISP_SVGA
|
|
|
|
;; To cope with Helix SoftWare "Netroom 2.20" DOS extender
|
|
;; which only maps in pages of the BIOS that have vectors
|
|
;; we must ensure that something points at page F6xxx
|
|
;; else we end up with the scratch area on top of some
|
|
;; DOS program or driver!
|
|
|
|
ORG 06f00h ; UNEXP_INT_OFFSET
|
|
BOP BIOS_UNEXP_INT
|
|
IRET
|
|
|
|
.386
|
|
; These are the virtualisation instructions needed for the 386.
|
|
|
|
ORG 3000h ; BIOS_STI_OFFSET
|
|
STI
|
|
BOP 0feh
|
|
|
|
ORG 3010h ; BIOS_CLI_OFFSET
|
|
CLI
|
|
BOP 0feh
|
|
|
|
ORG 3020h ; BIOS_INB_OFFSET
|
|
IN al,dx
|
|
BOP 0feh
|
|
|
|
ORG 3030h ; BIOS_INW_OFFSET
|
|
IN ax,dx
|
|
BOP 0feh
|
|
|
|
ORG 3040h ; BIOS_IND_OFFSET
|
|
IN eax,dx
|
|
BOP 0feh
|
|
|
|
ORG 3050h ; BIOS_OUTB_OFFSET
|
|
OUT dx,al
|
|
BOP 0feh
|
|
|
|
ORG 3060h ; BIOS_OUTW_OFFSET
|
|
OUT dx,ax
|
|
BOP 0feh
|
|
|
|
ORG 3070h ; BIOS_OUTD_OFFSET
|
|
OUT dx,eax
|
|
BOP 0feh
|
|
|
|
ORG 3080h ; BIOS_WRTB_OFFSET
|
|
MOV [edx],al
|
|
BOP 0feh
|
|
|
|
ORG 3090h ; BIOS_WRTW_OFFSET
|
|
MOV [edx],ax
|
|
BOP 0feh
|
|
|
|
ORG 30a0h ; BIOS_WRTD_OFFSET
|
|
MOV [edx],eax
|
|
BOP 0feh
|
|
|
|
ORG 30b0h ; BIOS_RDB_OFFSET
|
|
MOV al, [edx]
|
|
BOP 0feh
|
|
|
|
ORG 30c0h ; BIOS_RDW_OFFSET
|
|
MOV ax, [edx]
|
|
BOP 0feh
|
|
|
|
ORG 30d0h ; BIOS_RDD_OFFSET
|
|
MOV eax, [edx]
|
|
BOP 0feh
|
|
|
|
ORG 30e0h ; BIOS_YIELD_VM_OFFSET
|
|
MOV AX, 1680h ; Yeild VM time slice
|
|
INT 2fh
|
|
BOP 0feh
|
|
|
|
ORG 30f0h ; BIOS_STOSB_OFFSET
|
|
push es
|
|
push ds
|
|
pop es
|
|
xchg edx,edi ; dest lin addr
|
|
db 67h
|
|
db 66h
|
|
rep stosb
|
|
xchg edx,edi
|
|
pop es
|
|
BOP 0feh
|
|
|
|
ORG 3110h ; BIOS_STOSW_OFFSET
|
|
push es
|
|
push ds
|
|
pop es
|
|
xchg edx,edi ; dest lin addr
|
|
db 67h
|
|
rep stosw
|
|
xchg edx,edi
|
|
pop es
|
|
BOP 0feh
|
|
|
|
ORG 3130h ; BIOS_STOSD_OFFSET
|
|
push es
|
|
push ds
|
|
pop es
|
|
xchg edx,edi ; dest lin addr
|
|
db 67h
|
|
db 66h
|
|
rep stosw
|
|
xchg edx,edi
|
|
pop es
|
|
BOP 0feh
|
|
|
|
ORG 3200h ; BIOS_BAD_OFFSET
|
|
db 0c5h
|
|
db 0c5h ; illegal instruction
|
|
BOP 0feh
|
|
|
|
;; N.B. DISKWAIT_OFFSET is at "org 329fh"
|
|
|
|
code ends
|
|
|
|
end
|
|
|