Files
DR-DOS-OpenDOS/IBMBIO/INIT.ASM
2020-11-04 23:59:28 +01:00

1081 lines
25 KiB
NASM

; File : $Workfile$
;
; Description :
;
; Original Author : DIGITAL RESEARCH
;
; Last Edited By : $CALDERA$
;
;-----------------------------------------------------------------------;
; Copyright Work of Caldera, Inc. All Rights Reserved.
;
; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
; CIVIL LIABILITY.
;-----------------------------------------------------------------------;
;
; *** Current Edit History ***
; *** End of Current Edit History ***
;
; $Log$
; INIT.ASM 1.25 93/12/07 15:51:27
; Move int13pointer to offset 0B4h as some app expects it there
; INIT.ASM 1.24 93/11/18 18:57:20
; Increase amount reserved for COMMAND.COM by 256 bytes
; INIT.ASM 1.23 93/11/17 19:29:26
; Change default DEBLOCK seg to FFFF for performance reasons
; INIT.ASM 1.19 93/07/22 19:43:59
; switch over to REQUEST.EQU
; ENDLOG
include BIOSGRPS.EQU
include DRMACROS.EQU
include IBMROS.EQU
include MSDOS.EQU
include REQUEST.EQU ; request header equates
include BPB.EQU
include UDSC.EQU
include DRIVER.EQU
; IBM AT Hardware equates
COMPRESSED equ TRUE ; enables compressed changes.
; a little macro to help locate things
; it warns us when the ORG get trampled on
orgabs MACRO address
local was,is
was = offset $
org address
is = offset $
if was GT is
if2
%OUT ERROR - absolute data overwritten !! moving it
endif
org was
endif
ENDM
jmpfar MACRO address, fixup
db 0EAh ; jmpf opcode
dw CG:address ; offset of destination
fixup dw 0EDCh ; segment of destination
ENDM
callfar MACRO address, fixup
db 09Ah ; callf opcode
dw CG:address ; offset of destination
fixup dw 0EDCh ; segment of destination
ENDM
F5KEY equ 3F00h
F8KEY equ 4200h
IVECT segment at 0000h
org 0000h*4
i0off dw ?
i0seg dw ?
org 0001h*4
i1off dw ?
i1seg dw ?
org 0003h*4
i3off dw ?
i3seg dw ?
org 0004h*4
i4off dw ?
i4seg dw ?
org 0015h*4
i15off dw ?
i15seg dw ?
org 0019h*4
i19off dw ?
i19seg dw ?
org 001Eh*4
i1Eptr label dword
i1Eoff dw ?
i1Eseg dw ?
org 002Fh*4
i2Fptr label dword
i2Foff dw ?
i2Fseg dw ?
org 006Ch*4
i6Cptr label dword
i6Coff dw ?
i6Cseg dw ?
IVECT ends
CGROUP group CODE, RCODE, ICODE
CG equ offset CGROUP
CODE segment 'CODE'
Assume CS:CGROUP, DS:Nothing, ES:Nothing, SS:Nothing
public strat
extrn ConsoleTable:word
extrn ClockTable:word
extrn SerParCommonTable:word
extrn DiskTable:near
extrn Int13Deblock:near
extrn Int13Unsure:near
extrn Int2FHandler:near
extrn ResumeHandler:near
extrn biosinit_end:byte ; End of the BIOS Init Code and Data
extrn biosinit:near
extrn boot_options:word
extrn rcode_fixups:word
extrn rcode_seg:word
extrn rcode_offset:word
extrn rcode_len:word
extrn icode_len:word
extrn current_dos:word
extrn device_root:dword
extrn mem_size:word
extrn ext_mem_size:word
extrn init_buf:byte
extrn init_drv:byte
extrn init_runit:byte
extrn comspec_drv:byte
extrn init_flags:word
include biosmsgs.def ; Include TFT Header File
Public A20Enable
A20Enable proc near
;========
; This location is fixed up at run time to be a RET
; If the BIOS is relocated to the HMA then it is fixed up again to be
; CALLF IBMDOS:A20Enable; RET
; Calling this location at run time will ensure that the HMA is mapped
; in so we can access the HMA code.
;
A20Enable endp
init proc near ; this is at BIOSCODE:0000h
ifndef COPYPROT
jmp init0 ; jump to reusable init space
else
extrn protect:near ; Jump to Copy protection code
jmp protect ; which will return control to
endif ; INIT0 on completion
init endp
compflg label word
ifdef COPYPROT
dw ' ' ; stops any compression working
else
dw offset CGROUP:INITDATA ; compresses from INITDATA onwards
endif ; this word set to 0 when compressed
orgabs 06h
db 'COMPAQCompatible'
dw offset CGROUP:RCODE ; lets find offset of RCODE
MemFixup dw 0 ; and its relocated segment
Public cleanup
cleanup PROC far ; BIOSINIT will call here later
ret
cleanup endp
; Local single character buffer for Ctrl-Break handling
public serparFlag, serparChar
serparFlag db 4 dup (FALSE) ; we haven't got any yet
serparChar db 4 dup (?) ; will store one character
; Device driver headers for serial/parallel devices
con_drvr dw CG:aux_drvr, 0 ; link to next device driver
dw DA_CHARDEV+DA_SPECIAL+DA_ISCOT+DA_ISCIN+DA_IOCTL
dw CG:strat, CG:IntCon
db 'CON '
aux_drvr dw CG:prn_drvr, 0 ; link to next device driver
dw DA_CHARDEV
dw CG:strat, CG:IntCOM1
db 'AUX '
prn_drvr dw CG:clock_drvr, 0 ; link to next device driver
dw DA_CHARDEV
dw CG:strat, CG:IntLPT1
db 'PRN '
clock_drvr dw disk_drvr, 0 ; link to next device driver
dw DA_CHARDEV+DA_ISCLK
dw CG:strat, CG:IntClock
db 'CLOCK$ '
com1_drvr dw CG:lpt1_drvr, 0 ; link to next device driver
dw DA_CHARDEV
dw CG:strat, CG:IntCOM1
db 'COM1 '
com2_drvr dw CG:com3_drvr, 0 ; link to next device driver
dw DA_CHARDEV
dw CG:strat, CG:IntCOM2
db 'COM2 '
com3_drvr dw CG:com4_drvr, 0 ; link to next device driver
dw DA_CHARDEV
dw CG:strat, CG:IntCOM3
db 'COM3 '
IFDEF EMBEDDED
extrn rdisk_drvr:near
com4_drvr dw CG:rdisk_drvr, 0 ; link to next device driver
ELSE
com4_drvr dw -1, -1 ; link to next device driver
ENDIF
dw DA_CHARDEV
dw CG:strat, CG:IntCOM4
db 'COM4 '
orgabs 0b4h ; save address at fixed location
; for dirty apps
Public i13pointer, i13off_save, i13seg_save
i13pointer label dword ; address of ROS Int 13h entry
i13off_save dw ?
i13seg_save dw ?
orgabs 0b8h ; REQ_HDR
public req_ptr, req_off, req_seg
req_ptr label dword
req_off dw 0 ;** fixed location **
req_seg dw 0 ;** fixed location **
strat proc far
mov cs:req_off,bx
mov cs:req_seg,es
ret
strat endp
lpt1_drvr dw CG:lpt2_drvr, 0 ; link to next device driver
dw DA_CHARDEV
dw CG:strat, CG:IntLPT1
db 'LPT1 '
lpt2_drvr dw CG:lpt3_drvr, 0 ; link to next device driver
dw DA_CHARDEV
dw CG:strat, CG:IntLPT2
db 'LPT2 '
lpt3_drvr dw CG:com2_drvr, 0 ; link to next device driver
dw DA_CHARDEV
dw CG:strat, CG:IntLPT3
db 'LPT3 '
orgabs 100h ; save vectors at fixed location
; for dirty apps
Public orgInt13
NUM_SAVED_VECS equ 5
vecSave db 10h
dw 0,0
db 13h
orgInt13 dw 0,0
db 15h
dw 0,0
db 19h
dw 0,0
db 1Bh
dw 0,0
Int19Trap:
cld
cli ; be sure...
push cs
pop ds
lea si,vecSave
mov cx,NUM_SAVED_VECS ; restore this many vectors
Int19Trap10:
xor ax,ax ; zero AH for lodsb
mov es,ax ; ES -> interrupt vectors
lodsb ; AX = vector to restore
shl ax,1
shl ax,1 ; point at address
xchg ax,di ; ES:DI -> location to restore
movsw
movsw ; restore this vector
loop Int19Trap10 ; go and do another
int 19h ; and go to original int 19...
orgabs 16ch ; PRN:/AUX: the device number
devno db 0,0 ;** fixed location **
Public NumDiskUnits, DeblockSeg
disk_drvr dw CG:com1_drvr, 0 ; link to next driver
dw DA_NONIBM+DA_GETSET+DA_REMOVE+DA_BIGDRV
dw CG:strat, CG:IntDisk
NumDiskUnits db 5, 7 dup (?)
dw 0EDCh ; checked by DRIVER.SYS
dw 0 ; was allocate UDSC
DeblockSeg dw 0A000h ; segment we start deblocking
IntLPT1: ; LPT1
call DeviceDriver
dw 0
IntLPT2: ; LPT2
call DeviceDriver
dw 1
IntLPT3: ; LPT3
call DeviceDriver
dw 2
IntCOM1: ; AUX = COM1
call DeviceDriver
dw 3
IntCOM2: ; COM2
call DeviceDriver
dw 4
IntCOM3: ; COM3
call DeviceDriver
dw 5
IntCOM4: ; COM4
call DeviceDriver
dw 6
IntCon:
call DeviceDriver
dw offset CGROUP:ConsoleTable
IntClock:
call DeviceDriver
dw offset CGROUP:ClockTable
Public IntDiskTable
IntDisk:
call DeviceDriver
IntDiskTable:
dw offset CGROUP:DiskTable
DeviceDriver proc near
call A20Enable ; make sure A20 is on
jmpfar DriverFunction, DriverFunctionFixup
DeviceDriver endp
extrn i13_AX:word
Public Int13Trap
Int13Trap proc far
;--------
; The Int 13 code is in low memory for speed, with unusual conditions
; having the overhead of A20Enable calls
;
cmp ah,ROS_FORMAT ; ROS format function?
je Int13TrapFormat
Int13Trap10:
mov cs:i13_AX,ax ; save Op/Count in case of error
clc
pushf ; fake an Int
call cs:i13pointer ; call the ROM BIOS
jc Int13Trap20 ; check for error
ret 2 ; none, so return to caller
Int13Trap20:
cmp ah,9 ; it it a DMA error ?
je Int13TrapDMA ; then deblock it
call Int13TrapUnsure ; else declare floppy drive unsure
stc ; restore error flag
ret 2 ; return to user
Int13TrapFormat:
call Int13TrapUnsure ; mark media as unsure
jmps Int13Trap10 ; and resume
Int13TrapDMA:
call A20Enable ; make sure A20 is on
jmpfar Int13Deblock, Int13DeblockFixup
Int13TrapUnsure proc near
call A20Enable ; make sure A20 is on
callfar Int13Unsure, Int13UnsureFixup
ret
Int13TrapUnsure endp
Int13Trap endp
Public Int2FTrap
Int2FTrap proc far
;--------
jmpfar Int2FHandler, Int2FFixup
Int2FTrap endp
Resume proc far
;-----
call A20Enable ; make sure A20 is on
jmpfar ResumeHandler, ResumeFixup
Resume endp
Int0Trap proc far
;-------
call A20Enable ; make sure A20 is on
jmpfar Int0Handler, Int0Fixup
Int0Trap endp
Public FastConsole
FastConsole proc far
;----------
; RAM entry to ensure INT29 vector is below INT20 vector
; We keep the normal path low to maxmimise performance, but on backspace we
; take the A20Enable hit and call high for greater TPA.
;
pushx <ax, bx, si, di, bp> ; old ROS corrupts these
cmp al,8 ; back space character
je Fastcon30 ; special case
Fastcon10:
mov ah,0Eh ; use ROS TTY-like output function
mov bx,7 ; use the normal attribute
int VIDEO_INT ; output the character in AL
Fastcon20:
popx <bp, di, si, bx, ax>
iret
Fastcon30:
call A20Enable ; make sure A20 is on
jmpfar OutputBS, OutputBSFixup ; call up to the HMA
FastConsole endp
Public ControlBreak
ControlBreak proc far
;-----------
mov cs:word ptr local_char,'C'-40h + (256*TRUE)
;; mov local_char,'C'-40h ; force ^C into local buffer
;; mov local_flag,TRUE ; indicate buffer not empty
Int1Trap:
Int3Trap:
Int4Trap:
iret
ControlBreak endp
public daycount
daycount dw 0
; More Disk Data
public local_buffer,local_id,local_pt
local_buffer db 512 dup (?) ; local deblocking buffer
SECSIZE equ 512
IDOFF equ SECSIZE-2 ; last word in boot sector is ID
PTOFF equ IDOFF-40h ; 4*16 bytes for partition def's
local_id equ word ptr local_buffer + IDOFF
local_pt equ word ptr local_buffer + PTOFF
public bpbs,bpb160,bpb360,bpb720,NBPBS
; List of BPBs that we usually support
bpb160 BPB <512,1,1,2, 64, 40*1*8,0FEh,1, 8,1,0,0>
bpb180 BPB <512,1,1,2, 64, 40*1*9,0FCh,2, 9,1,0,0>
bpb320 BPB <512,2,1,2,112, 40*2*8,0FFh,1, 8,2,0,0>
bpb360 BPB <512,2,1,2,112, 40*2*9,0FDh,2, 9,2,0,0>
bpb1200 BPB <512,1,1,2,224,80*2*15,0F9h,7,15,2,0,0>
bpb720 BPB <512,2,1,2,112, 80*2*9,0F9h,3, 9,2,0,0>
bpb1440 BPB <512,1,1,2,224,80*2*18,0F0h,9,18,2,0,0>
bpb2880 BPB <512,2,1,2,240,80*2*36,0F0h,9,36,2,0,0>
NBPBS equ 8
; The following is a template, that gets overwritten
; with the real parameters and is used while formatting
public local_parms,parms_spt,parms_gpl
public layout_table,bpbtbl
local_parms db 11011111b ; step rate
db 2 ; DMA mode
db 37 ; 2*18.2 = 2 second motor off
db 2 ; 512 bytes per sector
parms_spt db 18 ; sectors per track
db 2Ah ; gap length for read/write
db 0FFh ; data length (128 byte/sector only)
parms_gpl db 50h ; data length for format
db 0F6h ; fill byte for format
db 15 ; head settle time in ms
db 8 ; motor on delay in 1/8s
; The BPB table need not survive config time, so share with layout table
bpbtbl label word
MAX_SPT equ 40
layout_table label word ; current # of sectors/track
S = 1
rept MAX_SPT
; C H S N
; - - - -
db 0, 0, S, 2
S = S + 1
endm
orgabs 600h ; CON: one character look-ahead buffer
; nb. it's at 61B in DOS 4.0
Public local_char, local_flag
local_char db 0 ;** fixed location **
local_flag db 0 ;** fixed location **
public endbios
endbios dw offset CGROUP:RESBIOS ; pointer to last resident byte
CODE ends
ICODE segment 'ICODE' ; reusable initialization code
Assume CS:CGROUP, DS:CGROUP, ES:CGROUP, SS:Nothing
bpbs dw CG:bpb360 ; 0: 320/360 Kb 5.25" floppy
dw CG:bpb1200 ; 1: 1.2 Mb 5.25" floppy
dw CG:bpb720 ; 2: 720 Kb 3.5" floppy
dw CG:bpb360 ; 3: (8" single density)
dw CG:bpb360 ; 4: (8" double density)
dw CG:bpb360 ; 5: hard disk
dw CG:bpb360 ; 6: tape drive
dw CG:bpb1440 ; 7: 1.44 Mb 3.5" floppy
dw CG:bpb1440 ; 8: Other
dw CG:bpb2880 ; 9: 2.88 Mb 3.5" floppy
Public init0
init0 proc near
;
; We now uncompress to > (7C00h (ie. boot stack) - 700h (ie. base of code)
; This means our stack collides with our code, very bad news.
; To avoid this we switch stacks into a safer area ie. 0C000h
; The floppy parameters also live at 7C00, so we have to relocate these
; before we expand.
mov cs:byte ptr A20Enable,0C3h
; fixup the RET
mov sp, 0C000h ; switch to magic stack
sti
cld
push cx ; save entry registers
push di ; (important in ROM systems)
xor si,si
mov ds,si
mov es,si
Assume DS:IVECT, ES:IVECT
mov di,522h ; ES:DI -> save area for parameters
lds si,i1Eptr ; DS:SI -> FD parameters for ROS
Assume DS:Nothing
mov i1Eoff,di
mov i1Eseg,es ; setup new location
mov cx,11
rep movsb
mov es:byte ptr 0-7[di],36 ; enable read/writing of 36 sectors/track
pop di
pop cx
if COMPRESSED
mov si, cs ; preserve entry registers
mov ds, si ; other than si, ds and es
mov es, si
xor si, si
mov si, compflg ; Get Compresed BIOS Flag
or si, si ; Set to Zero if the BIOS has
jnz not_compressed ; been compressed
mov si, CG:INITDATA
push di ; bios_seg
push ax ; bdos_seg
push bx ; initial drives
push cx ; memory size
push dx ; initial flags
lea cx, biosinit_end
sub cx, si
inc cx ; length of compressed part plus one
mov di, cx
neg di ; furthest offset we can use
and di, 0fff0h ; on the next para below
push di
push si
shr cx, 1
rep movsw ; take a copy
pop di ; di is now -> compressed dest
pop si ; this is now -> compressed source
bios_r20:
lodsw ; get control word
mov cx,ax ; as a count
jcxz bios_r40 ; all done
test cx,8000h ; negative ?
jnz bios_r30 ; yes do zeros
rep movsb ; else move in data bytes
jmp short bios_r20 ; and to the next
bios_r30:
and cx,7fffh ; remove sign
jcxz bios_r20 ; none to do
xor ax,ax
rep stosb ; fill with zeros
jmp short bios_r20
bios_r40:
pop dx
pop cx
pop bx
pop ax
pop di
not_compressed:
endif
mov si,cs
mov ds,si ; DS -> local data segment
cmp dl,0ffh ; booting from ROM?
jz rom_boot
cmp si,1000h ; test if debugging
jb disk_boot ; skip if not
; When the BIOS is loaded by the DOSLOAD or LOADER utilities under
; Concurrent for DEBUGGING or in a ROM system then on entry AX
; contains the current location of the BDOS and CX the memory Size.
; Bx is the current code segment
mov rcode_seg,dx ; rom segment of bios
mov current_dos,ax ; current location of the BDOS
mov mem_size,cx ; total memory size
mov init_drv,bl ; initial drive
mov comspec_drv,bh ;
mov init_buf,3 ; assume default # of buffers
mov init_flags,3
jmp bios_exit
rom_boot: ; BIOS is copied from ROM:
; DL = 0FFh
; AX = segment address of DRBDOS
; BH = COMSPEC drive
; BL = INIT_DRV
mov rcode_seg,di ; DI = BIOS ROM SEG
mov current_dos,ax ; current location of the BDOS
mov init_drv,bl ; initial drive C:
mov comspec_drv,bh ; commspec drive C:
mov init_flags,3 ; it is a ROM system, use comspec drive
jmps rom_boot10 ; common code
disk_boot:
mov rcode_seg,cs
sub ax,ax
mov current_dos,ax ; current BDOS location to disk load
xchg ax,dx ; AL = boot drive
mov init_runit,al ; save the ROS unit
test al,al ; test the boot drive
jz floppy_boot ; skip if floppy boot
mov al,2 ; it's drive C:
floppy_boot:
mov init_drv,al ; set boot drive
rom_boot10:
pushx <ds, es> ; save registers
sub bx,bx
mov ds,bx ; DS:BX -> interrupt vectors
Assume DS:IVECT
push cs ; we want to save vectors some
pop es ; locally
lea di,vecSave
mov cx,NUM_SAVED_VECS ; restore this many vectors
SaveVectors:
xor ax,ax ; zero AH
mov al,es:[di] ; AX = vector to save
inc di ; skip to save position
shl ax,1
shl ax,1 ; point at address
xchg ax,si ; DS:SI -> location to save
movsw
movsw ; save this vector
loop SaveVectors ; go and do another
mov i0off,CG:Int0Trap
mov i0seg,cs ; now grab int0 vector
mov i1off,CG:Int1Trap
mov i1seg,cs ; now grab int1 vector
mov i3off,CG:Int1Trap
mov i3seg,cs ; now grab int3 vector
mov i4off,CG:Int1Trap
mov i4seg,cs ; now grab int4 vector
mov i19off,CG:Int19Trap
mov i19seg,cs ; now grab int19 vector
popx <es, ds>
Assume DS:CGROUP, ES:CGROUP
call get_boot_options ; look for user keypress
mov boot_options,ax ; return any options
mov ah,EXT_MEMORY
int SYSTEM_INT ; find out how much extended memory
jnc bios_extmem
xor ax,ax ; say we have no memory
bios_extmem:
mov ext_mem_size,ax ; we have and store for reference
mov init_buf,3 ; assume default of 3 buffers
int MEMORY_INT ; get amount of conventional memory
cmp ax,128
jbe bios_mem
mov init_buf,5 ; use 5 buffers if > 128K of memory
bios_mem: ; get amount of conventional memory
mov cl,6 ; in kilobytes (AX)
shl ax,cl ; convert Kb's to paragraphs
mov mem_size,ax ; set end of TPA
bios_exit:
; The following code performs the fixups necessary for ROM executable
; internal device drivers.
mov ax,cs ; check if we are on a rommed system
cmp ax,rcode_seg
jne keep_rcode ; if so no relocation required
mov ax,CG:RCODE
mov rcode_offset,ax ; fixup variable need
mov bx,CG:IDATA
sub bx,ax
mov icode_len,bx ; during init we need RCODE and ICODE
mov bx,CG:RESUMECODE
sub bx,ax
mov rcode_header,bx
mov rcode_len,bx ; afterwards we just need RCODE
keep_rcode:
; If the system ROM BIOS supports RESUME mode then it will call Int 6C
; when returning from sleep mode. We take this over and reset the clock
; based upon the RTC value. To save space we only relocate the code if
; required.
;
mov ax,4100h ; does the BIOS support resume mode
xor bx,bx
int 15h ; lets ask it
jc resume_exit
push ds
xor ax,ax
mov ds,ax ; DS = vectors
Assume DS:IVECT
mov i6Coff,CG:Resume
mov i6Cseg,cs ; point Int 6C at resume code
Assume DS:CGROUP
pop ds
mov ax,cs ; check if we are on a rommed system
cmp ax,rcode_seg
jne resume_exit ; if so nothing extra to keep
mov ax,CG:RESBIOS
sub ax,CG:RCODE
mov rcode_header,ax ; keep Resume code as well...
mov rcode_len,ax ; afterwards we just need RCODE
resume_exit:
mov ax,CG:ENDCODE ; discard RCODE (we will relocate it)
mov endbios,ax
mov rcode_fixups,CG:bios_fixup_tbl
mov bx,CG:con_drvr ; get first device driver in chain
mov word ptr device_root+0,bx
mov word ptr device_root+2,ds
init1:
cmp word ptr [bx],0FFFFh ; last driver in BIOS?
je init3
mov 2[bx],ds ; fix up segments in driver chain
mov bx,[bx]
jmps init1
init3:
jmp biosinit ; jump to BIOS code
init0 endp
get_boot_options:
;----------------
; On Entry:
; None
; On Exit:
; AX = boot options
mov si,offset CGROUP:starting_dos_msg
lodsb ; get 1st character (never NULL)
get_boot_options10:
mov ah,0Eh
mov bx,7
int VIDEO_INT ; TTY write of character
lodsb ; fetch another character
test al,al ; end of string ?
jnz get_boot_options10
call option_key ; poll keyboard for a while
jnz get_boot_options20 ; if key available return that
mov ah,2 ; else ask ROS for shift state
int 16h
and ax,3 ; a SHIFT key is the same as F5KEY
jz get_boot_options20
mov ax,F5KEY ; ie. bypass everything
get_boot_options20:
ret
option_key:
;----------
; On Entry:
; None
; On Exit:
; AX = keypress if interesting (F5/F8)
; ZF clear if we have an interesting key
;
; Poll keyboard looking for a key press. We do so for a maximum of 36 ticks
; (approx 2 seconds).
;
xor ax,ax
int 1Ah ; get ticks in DX
mov cx,dx ; save in CX for later
option_key10:
push cx
mov ah,1
int 16h ; check keyboard for key
pop cx
jnz option_key30 ; stop if key available
push cx
xor ax,ax
int 1Ah ; get ticks in DX
pop cx
sub dx,cx ; work out elapsed time
cmp dx,36 ; more than 2 secs ?
jb option_key10
option_key20:
xor ax,ax ; timeout, set ZF, no key pressed
ret
option_key30:
cmp ax,F5KEY ; if it is a key we want then
je option_key40 ; read it, else just leave
cmp ax,F8KEY ; in the type-ahead buffer
jne option_key20
option_key40:
xor ax,ax
int 16h ; read the key
test ax,ax ; clear ZF to indicate we have a key
ret
ICODE ends
INITDATA segment 'INITDATA'
; This is a zero terminated list of locations to be fixed up with the
; segment of the relocated BIOS RCODE
bios_fixup_tbl dw CG:MemFixup
dw CG:OutputBSFixup
dw CG:DriverFunctionFixup
dw CG:Int0Fixup
dw CG:Int13DeblockFixup
dw CG:Int13UnsureFixup
dw CG:Int2FFixup
dw CG:ResumeFixup
IFDEF EMBEDDED
dw CG:RdiskFixup
endif
dw 0
INITDATA ends
CODE segment 'CODE'
IFDEF EMBEDDED
extrn RdiskFixup:word
endif
CODE ends
RCODE_ALIGN segment public para 'RCODE'
ifndef ROMSYS
db 1100h dup(0) ; reserve space for command.com
endif
RCODE_ALIGN ends
RCODE segment public word 'RCODE'
rcode_header dw 0
Public DataSegment
DataSegment dw 0070h ; segment address of low data/code
; Called to vector to appropriate sub-function in device driver
; The Function table address immediately follows the near call, so we can index
; into it using the return address. If the offset is in the range 0-6 it's
; actually a device number for the serial/parallel driver
;
;
; On Entry to subfunctions ES:BX -> req_hdr, DX = devno (serial/parallel)
;
FunctionTable struc
FunctionTableMax db ?
FunctionTableEntry dw ?
FunctionTable ends
Public DriverFunction
DriverFunction proc far
cld
sub sp,(size P_STRUC)-4 ; make space for stack variables
push bp ; (BP and RET are included)
mov bp,sp ; set up stack frame
pushx <ds,es>
pushx <ax,bx,cx,dx,si,di> ; save all registers
mov ds,cs:DataSegment
mov si,(size P_STRUC)-2[bp] ; get return address = command table
lodsw ; AX = following word
xchg ax,dx ; DX = device number (0-6)
mov si,offset CGROUP:SerParCommonTable
cmp dx,6 ; if not a device number it's a table
jbe DriverFunction10
mov si,dx ; DS:SI -> table
DriverFunction10:
les bx,req_ptr ; ES:BX -> request header
mov REQUEST_OFF[bp],bx
mov REQUEST_SEG[bp],es
mov al,es:RH_CMD[bx] ; check if legal command
cmp al,cs:FunctionTableMax[si]
ja cmderr ; skip if out of range
cbw ; convert to word
add ax,ax ; make it a word offset
add si,ax ; add index to function table
call cs:FunctionTableEntry[si]
les bx,REQUEST[bp]
cmddone:
or ax,RHS_DONE ; indicate request is "done"
mov es:RH_STATUS[bx],ax ; update the status for BDOS
popx <di,si,dx,cx,bx,ax> ; restore all registers
popx <es,ds>
pop bp
add sp,(size P_STRUC)-2 ; discard stack variables
ret
cmderr:
mov ax,RHS_ERROR+3 ; "invalid command" error
jmps cmddone ; return the error
DriverFunction endp
OutputBS proc far
;-------
; pushx <ax, bx, si, di, bp> ; these are on the stack
pushx <cx, dx>
mov ah,3 ; get cursor address
mov bh,0 ; on page zero
int VIDEO_INT ; BH = page, DH/DL = cursor row/col
test dx,dx ; row 0, col 0
jz OutputBS10 ; ignore if first line
dec dl ; are we in column 0?
jns OutputBS10 ; no, normal BS
dec dh ; else move up one line
push ds
xor ax,ax
mov ds,ax
mov dl,ds:byte ptr [44ah] ; DL = # of columns
dec dx ; DL = last column
pop ds
mov ah,2 ; set cursor, DH/DL = cursor, BH = page
int VIDEO_INT ; set cursor address
jmps OutputBS20
OutputBS10:
mov ax,0E08h ; use ROS TTY-like output function
mov bx,7 ; use the normal attribute
int VIDEO_INT ; output the character in AL
OutputBS20:
popx <dx, cx>
popx <bp, di, si, bx, ax>
iret
OutputBS endp
Int0Handler proc far
;----------
cld
push cs
pop ds
mov si,CG:div_by_zero_msg ; DS:SI points at ASCIZ message
mov bx,STDERR ; to STDERR - where else ?
mov cx,1 ; write one at a time
int0_loop:
mov dx,si ; DS:DX points at a char
lodsb ; lets look at it first
test al,al ; end of string ?
je int0_exit
mov ah,MS_X_WRITE ; write out the error
int DOS_INT
jnc int0_loop ; if it went OK do another
int0_exit:
mov ax,MS_X_EXIT*256+1 ; time to leave - say we got an error
int DOS_INT ; go for it!
Int0Handler endp
RCODE ends
end init