⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 config.a86

📁 与MS-DOS兼容的DOS操作系统
💻 A86
📖 第 1 页 / 共 3 页
字号:
;	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 + -