📄 config.a86
字号:
; The device driver initialised OK so now build/update internal
; tables based on the device driver type.
;
; AX = next available paragraph
; DS:BX = request header
; ES:DI = device driver header
;
dev_i30: ; DEV_INIT OK so update the Top of
mov mem_current,ax ; memory field
test es:DH_ATTRIB[di],DA_CHARDEV
jz dev_i40
call char_device ; Handle Initialization of all
jmps dev_i50 ; character devices
dev_i40:
call block_device ; Handle Initialization of all
; jmps dev_i50 ; Block Devices
dev_i50:
pop di ! pop es ; Retrieve the current device header
push es:DH_NEXTSEG[di] ; save next entry on the list
push es:DH_NEXTOFF[di] ; while we deal with existing one
mov es:DH_NEXTOFF[di],0FFFFh; terminate the list
call device_insert ; and insert into the list
pop di
pop es ; go round till the end
dev_i60:
pop si ; recover cmdline for next device
cmp di,0FFFFh ; was that the last device to
jne dev_i10 ; initialise, no do next
mov bx,offset request_hdr ; ds:bx -> command block
mov ax,ds:RH_STATUS ; return Status Register
and ax,80FFh ; is there an error ?
js dev_i70
xor ax,ax ; no, return success
dev_i70:
ret
public init_static_request
init_static_request:
; Set up request header for INIT command.
sub ax,ax ; get a convenient zero
mov ds:RH_LEN,RH0_LEN ; Init Request Length
mov ds:RH_UNIT,al ; relative drive always 0
mov ds:RH_CMD,CMD_INIT ; Init Command
mov ds:RH_STATUS,ax ; Zero Status Register
mov ds:RH0_BPBOFF,si ; Save the command line offset and
mov ds:RH0_BPBSEG,ds ; Segment in the BPB Pointer
mov al,next_drv ; the first drive for this device
sub al,preload_drv ; (not including preloaded devices)
mov ds:RH0_DRIVE,al ; will be allocated as NEXT_DRV
;;; mov es:DH_NEXTSEG[di],0 ; force seg to zero (386max 4.05)
ret
dev_init:
;--------
; On Entry:
; ES:DI -> device driver header
; DS:BX -> req header
; DS:SI -> command line
; On Exit:
; ES:DI/DS:BX <preserved>
;
mov ax,es:DH_STRATEGY[di] ; Set up the STRATEGY Entry Point
mov strategy_off,ax
mov strategy_seg,es
mov ax,es:DH_INTERRUPT[di] ; Set up the INTERRUPT Entry Point
mov interrupt_off,ax
mov interrupt_seg,es
call init_static_request
push ds ! push es ; Save Segment registers
push bx ! push si ! push di ; and pointers (not all preserve them)
push ds ! pop es ; ES -> Points at the Data Segment
mov ds,strategy_seg ; DS == Device Drive Segment
mov si,di ; DS:SI -> device driver header
callf cs:strategy ; Call Device Strategy Routine
callf cs:interrupt ; Call Device Interrupt Routine
pop di ! pop si ! pop bx ; recover the pointers
pop es ! pop ds ; Restore Segment Registers
mov es:DH_NEXTSEG[di],es ; ignore segment - it MUST be same one
ret
;
; Character Device Driver Initialised OK so now build/update internal
; tables based on the device driver type.
;
; DS:BX Request Header
; ES:DI Device Driver Header
;
char_device:
test es:DH_ATTRIB[di],DA_ISCIN
jz char_d10 ; is this the standard console device?
mov condev_off,di ; save console device driver address
mov condev_seg,es
ret
char_d10:
test es:DH_ATTRIB[di],DA_ISCLK
jz char_d20 ; is this the standard clock device?
mov clkdev_off,di ; save clock device driver address
mov clkdev_seg,es
char_d20:
ret
; Block device driver initialised OK. Save the values
; returned from the INIT call so we can later build all the
; required internal tables.
;
; entry: DS:BX -> request header
; ES:DI -> device driver header
;
public block_device
block_device:
mov al,BLKDEV_LENGTH ; bytes per block device table entry
mul byte ptr num_blkdev ; * # of block devices installed
add ax,offset blkdev_table ; AX -> block dev init result table
xchg ax,si ; pointer to next block device struct
mov devoff,di
mov devseg,es ; point to device driver header
mov 0[si],di
mov 2[si],es ; save device driver address for later
mov ax,ds:RH0_BPBOFF
mov 4[si],ax ; save BPB table address (offset)
mov ax,ds:RH0_BPBSEG
mov 6[si],ax ; save BPB table address (segment)
mov cl,ds:RH0_NUNITS
mov 8[si],cl ; get # of units supported by driver
mov es:DH_NAME[di],cl ; set # of units in device name
inc num_blkdev ; we've installed another block device
add next_drv,cl ; update drive base for next driver
add dev_count,cl ; number of new units
mov ax,boot_device ; now for Andy's bit about boot device
or ax,boot_device+2 ; have we already got a boot device?
jnz not_boot_dev
mov ch,init_drv
sub ch,next_drv ; is sub unit in this driver
ja not_boot_dev ; no, skip it
add ch,cl ; work out which sub unit it is
mov boot_drv,ch ; and remember it
mov boot_device,di
mov boot_device+2,es
not_boot_dev:
push si ! push es ! push di
mov cl,8[si]
mov ch,0 ; CX = # of drives found in driver
les si,4[si] ; ES:SI -> BPB array in BIOS
mov bpbseg,es ; remember the segment
blkdev_loop:
lods es:ax ; AX = offset of next BPB
push es ! push si ! push cx
mov bpboff,ax ; remember the offset
xchg ax,di ; ES:DI -> next BPB
mov ax,es:[di] ; AX = sector size for BPB
cmp ax,max_secsize ; new maximum for sector size
jbe blkdev_next1 ; skip if sector size not grown
mov max_secsize,ax ; else set new maximum
blkdev_next1:
mov dl,es:2[di] ; get sectors per cluster
mov dh,0 ; make this a word
mul dx ; AX = bytes per cluster
cmp ax,max_clsize ; more than previous maximum
jbe blkdev_next2 ; skip if no new high score
mov max_clsize,ax ; else record max. sector size
blkdev_next2:
les bx,func52_ptr ; ES:BX -> internal data
mov ax,es
or ax,bx ; DOS data area present yet?
jz blkdev_next3 ; skip if BDOS not present yet
call setup_drives ; update drives in BDOS data
mov es,mem_current ; MUST create a DDSC just after driver
add mem_current,(DDSC_LEN+15)/16
xor bp,bp ; ES:BP points to the DDSC
call setup_ddsc ; add new DDSC_ to chain
call setup_ldt ; initialise LDT for that drive
blkdev_next3:
pop cx ! pop si ! pop es
loop blkdev_loop ; repeat for all BPBs in driver
pop di ! pop es ! pop si
ret
resident_ddscs:
;--------------
; Allocate DDSC's for the resident device drivers - we can only do this
; after the DOS data area is established.
;
sub bx,bx ; start with 1st block device
mov cx,num_blkdev ; get # of block devices
jcxz res_ddsc40 ; skip if no block devices
res_ddsc10:
push bx ! push cx
mov ax,BLKDEV_LENGTH
mul bx
add ax,offset blkdev_table
xchg ax,si ; SI -> block device table
sub cx,cx
mov cl,8[si] ; CX = # of units on device
sub bx,bx ; BX = relative unit # * 2
mov rel_unit,bx ; start with relative unit # 0
res_ddsc20: ; CX = remaining units
push bx ! push cx ! push si ; BX = offset, SI -> drive structure
lodsw
mov devoff,ax ; save device header offset
lodsw
mov devseg,ax ; save device header segment
les si,[si] ; get offset of BPB array
mov ax,es:[bx+si] ; get offset for our BPB
mov bpboff,ax
mov bpbseg,es ; save pointer to BPB
les bp,res_ddsc_ptr ; point to position for DDSC_
add ds:word ptr res_ddsc_ptr,DDSC_LEN
call setup_ddsc ; setup one unit
pop si ! pop cx ! pop bx
inc bx ! inc bx ; increment (unit index*2)
loop res_ddsc20 ; repeat for next unit, same driver
pop cx ! pop bx
inc bx
loop res_ddsc10 ; repeat for next driver
res_ddsc40: ; all block devices done
ret
setup_ddsc:
;----------
; On Entry:
; ES:BP -> DDSC_ to initialise and link into chain
; bpbptr -> BPB to initialise from
; devseg:devoff -> device driver header
; abs_unit, rel_unit reflect drive
; On Exit:
; None
;
push ds
lds si,bpbptr ; DS:SI points to the BPB
mov ah,53h ; build DDSC from BPB call
int DOS_INT ; initialises the structure
pop ds
mov ax,devoff
mov es:DDSC_DEVOFF[bp],ax
mov ax,devseg
mov es:DDSC_DEVSEG[bp],ax
mov ax,abs_unit
inc abs_unit
mov es:DDSC_UNIT[bp],al ; set absolute unit (global)
mov ax,rel_unit
inc rel_unit
mov es:DDSC_RUNIT[bp],al ; set relative unit (driver relative)
mov ax,-1 ; set link to FFFFh:FFFFh
mov es:word ptr DDSC_LINK[bp],ax
mov es:word ptr DDSC_LINK+2[bp],ax
mov es:DDSC_FIRST[bp],al ; set drive never accessed flag
mov ax,es ; now link into device chain
;
les bx,func52_ptr ; ES:BX -> secret 52h data
lea bx,F52_DDSCPTR-(offset .DDSC_LINK)[bx]
setup_ddsc10:
cmp es:word ptr DDSC_LINK[bx],0FFFFh
je setup_ddsc20 ; is there another one ?
les bx,es:DDSC_LINK[bx] ; onto next DDSC_
jmps setup_ddsc10
setup_ddsc20: ; link new DDSC to end of chain
mov es:word ptr DDSC_LINK[bx],bp
mov es:word ptr DDSC_LINK+2[bx],ax
ret ; now RAF will be happy
Public setup_ldt
setup_ldt:
push ds
push es
les bx,func52_ptr ; get internal data in ES:BX
mov al,LDT_LEN ; we need this many bytes per drive
mul es:F52_LASTDRV[bx] ; *lastdrive
xchg ax,cx ; CX = size to initialise
mov al,es:F52_LASTDRV[bx] ; lastdrive
push ax ; save for later
les di,es:F52_PATHPTR[bx] ; now initialise the CSD's
xor al,al ; to zero
rep stosb ; zero them
pop ax ; recover lastdrive
xor bx,bx ; start with zero offset
xor cx,cx ; start with drive A
xchg al,cl ; AH = physical limit, CX logical limit
ldt_init:
push ax
push cx
push ax
lea di,LDT_NAME[bx]
add al,'A' ; make drive ASCII
stosb
mov ax,'\:' ; point at the root
stosw
mov ax,0FFFFh
lea di,LDT_BLK[bx] ; set to FFFF to force LDT_ rebuild
stosw ! stosw ! stosw ; next two words are FFFF too
; lea di,LDT_ROOTLEN[bx]
mov ax,2
stosw ; set the length field
pop ax
lds si,cs:func52_ptr ; get internal data in DS:SI
sub si,offset .DDSC_LINK
ldt_init20:
lds si,ds:DDSC_LINK[si] ; point to next PDT
cmp si,-1 ; skip if there isn't one
je ldt_init40
cmp al,ds:DDSC_UNIT[si] ; is this the DDSC for the drive
jne ldt_init20 ; if not try another
mov es:word ptr LDT_PDT[bx],si
mov es:word ptr LDT_PDT+2[bx],ds
cmp ds:DDSC_NFATS[si],0 ; no FATS, then it's a reserved drive
je ldt_init40
push es
push bx
push ax ; save drive we are processing
mov ax,4A11h
xor bx,bx
int 2Fh ; do an STACKER installation check
pop dx ; DL = drive we are processing
test ax,ax
mov ax,LFLG_PHYSICAL ; assume a physical drive
jnz ldt_init30 ; no STACKER, it's physical
sub cl,'A' ; zero base STACKER drive returned
cmp cl,dl ; should we check this drive ?
ja ldt_init30 ; below 1st drive, it's physical
push ax
push dx
mov ax,4A11h
mov bx,1 ; ask STACKER for host drive
int 2Fh
pop dx
pop ax
cmp bl,dl ; is this the host drive ?
jne ldt_init30
xor ax,ax ; drive is invalid
ldt_init30:
pop bx
pop es
mov es:LDT_FLAGS[bx],ax
ldt_init40:
add bx,LDT_LEN ; move onto next LDT_
pop cx
pop ax
inc ax ; and next drive
loop ldt_init ; done to lastdrive ? no, do another
pop es
pop ds
ret
Public device_insert
device_insert:
;-------------
; insert device drivers at ES:DI into global chain
; if we are initialising the resident device drivers then we don't have
; a global chain, so insert them on a local chain and try again later
push ds
lds bx,func52_ptr ; Internal Data Pointer
lea si,F52_DEVROOT[bx] ; DS:SI -> NUL device
mov ax,ds ; if BDOS data area isn't present
or ax,bx ; we are initialising resident
jnz dev_ins_next ; devices
push cs ! pop ds
mov si,offset resdev_chain ; it's resident devices
dev_ins_next:
cmp di,-1 ; end of device chain reached?
je devins_done ; yes, all devices inserted
mov ax,0[si]
mov dx,2[si] ; DX:AX = original chain
mov 0[si],di
mov 2[si],es ; link our device at head of chain
xchg ax,es:0[di] ; link old global chain to device
xchg dx,es:2[di] ; & get next device in local chain
mov di,ax ; point to next device in chain
mov es,dx
jmps dev_ins_next ; repeat until chain empty
devins_done:
pop ds
ret
public config_finish
config_finish: ; finish off configuration
;-------------
cmp resdev_off,-1 ; are resident devices already
je cfg_fin10 ; installed
les di,resdev_chain ; insert all the resident device
call device_insert ; drivers into DOS chain
call resident_ddscs ; build DDSC's for resident devices
mov resdev_off,-1 ; only do this once...
cfg_fin10:
les bx,func52_ptr ; ES:BX -> base of DOS variables
call setup_drives ; Update No of Physical Drives in case
; this is the first pass
call setup_ldt ; setup the ldt's
les bx,func52_ptr
lea di,F52_CLKDEV[bx] ; ES:DI -> clock ptr, console ptr
mov si,offset clkdev_off ; DS:SI -> local pointer values
movsw ; set offset of clock device driver
movsw ; set segment of clock device driver
movsw ; set offset of console device driver
movsw ; set segment of console device driver
call setup_doshndl ; Allocate DOS compatible Handles
; NB must immediately follow devices !
call setup_buffers ; allocate the requested #
ret
setup_buffers:
;-------------
; entry: num_buf = minimum # of buffers required
; 0 - use temporary high buffers
;
les bx,func52_ptr ; ES:BX -> internal data structure
mov ax,num_buf ; fill in info in DOS for diagnostic
mov es:F52_NUM_BUF[bx],ax ; programs
mov al,num_read_ahead_buf
mov es:F52_READ_AHEAD[bx],ax
mov ax,es:F52_SECSIZE[bx] ; get DOS data sector size
cmp ax,max_secsize ; has it been poked to a bigger value ?
ja setup_b10 ; if so we must discard anyway
mov ax,max_secsize ; get max. sector size found
setup_b10:
mov es:F52_SECSIZE[bx],ax ; update max. sector size in PCMODE
mov max_secsize,ax ; update max. sector size locally
add ax,offset .BCB_DATA ; add in the header size
mov es,init_dseg ; ES:DI -> init buffers
mov di,offset INIT_BUFFERS
mov cx,NUM_BUFFS ; CX buffs, DX in size, at ES:DI
mov dx,SIZEOF_BUFFS ; size of init buffers
cmp num_buf,0 ; (zero at init time)
je setup_b70 ; go ahead and initialise
push ax ; save size of buffer
mul num_buf ; AX = total bytes required
test dx,dx ; > 64 K ?
jz setup_b30
mov ax,0FFFFh ; do the maximum
setup_b30:
pop bx ; BX = size of a buffer
mov cx,ax ; CX bytes required
xor dx,dx
div bx ; AX = # buffers
push ax ; save # buffers
push bx ; save size of a buffer
push cx ; save bytes wanted
test buffersIn,BUFFERS_IN_HMA
stc ; do we want buffers at FFFF ?
jz setup_b40
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -