mirror of
https://github.com/SEPPDROID/DR-DOS-OpenDOS.git
synced 2025-10-22 07:54:28 +00:00
1081 lines
25 KiB
NASM
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
|