home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 June
/
SIMTEL_0692.cdr
/
msdos
/
dskutl
/
varvdisk.asm
< prev
next >
Wrap
Assembly Source File
|
1983-10-24
|
13KB
|
408 lines
;JS note, 8/1/83: This version of the variable-size virtual disk
; can handle up to 112 files. There seems not to be any need
; to change to a "double-sided" drive, but one must take care
; to zero out 7 sectors for the directory, rather than just the usual 4.
PAGE 66,132
;
; ******************************************************
; * PROLOG *
; * THIS IS AN INSTALLABLE DEVICE DIVER FOR AN *
; * IN STORAGE DISKETTE (VIRTUAL) WITH 180K CAPACITY. *
; ******************************************************
CSEG SEGMENT PARA PUBLIC 'CODE'
;
; M A C R O ( S )
;
STATUS MACRO STATE,ERR,RC
IFIDN <STATE>,<DONE>
OR ES:WORD PTR SRH_STA_FLD[BX],0100H
ENDIF
IFIDN <STATE>,<BUSY>
OR ES:WORD PTR SRH_STA_FLD[BX],0200H
ENDIF
IFIDN <ERR>,<ERROR>
OR ES:WORD PTR SRH_STA_FLD[BX],0100H
ENDIF
IFNB <RC>
OR ES:WORD PTR SRH_STA_FLD[BX],RC
ENDIF
ENDM
;
; E Q U A T E S
;
; READ/WRITE
;
SRH EQU 0 ;STATIC REQUEST HEADER START
SRH_LEN EQU 13 ; " " " LENGTH
SRH_LEN_FLD EQU SRH ; " " " " FIELD
SRH_UCD_FLD EQU SRH+1 ; " " " UNIT CODE FIELD
SRH_CCD_FLD EQU SRH+2 ; " " " COMMAND CODE FIELD
SRH_STA_FLD EQU SRH+3 ; " " " STATUS FIELD
SRH_RES_FLD EQU SRH+5 ; " " " RESERVED AREA FIELD
;
MD EQU SRH+SRH_LEN ;MEDIA DESCRIPTOR BYTE
MD_LEN EQU 1 ; " " " LENGTH
DTA EQU MD+MD_LEN ;DISK TRANSFER ADDRESS
DTA_LEN EQU 4 ; DTA LENGTH
COUNT EQU DTA+DTA_LEN ;BYTE/SECTOR COUNT
COUNT_LEN EQU 2 ; " " " LENGTH
SSN EQU COUNT+COUNT_LEN ;STARTING SECTOR NUMBER
SSN_LEN EQU 2 ; " " " LENGTH
;
; MEDIA CHECK
;
RET_BYTE EQU MD+MD_LEN ;BYTE RETURNED FROM DRIVER
;
; BUILD BPB
;
BPBA_PTR EQU DTA+DTA_LEN ;POINTER TO BPB
BPBA_PTR_LEN EQU 4 ; " " " LENGTH
;
; INIT
;
UNITS EQU SRH+SRH_LEN
UNITS_LEN EQU 1
BR_ADDR_0 EQU UNITS+UNITS_LEN
BR_ADDR_1 EQU BR_ADDR_0+2
BR_ADDR_LEN EQU 4
BPB_PTR_OFF EQU BR_ADDR_0+BR_ADDR_LEN
BPB_PTR_SEG EQU BPB_PTR_OFF+2
;
;
VDSK PROC FAR
ASSUME CS:CSEG,ES:CSEG,DS:CSEG
BEGIN:
START EQU $
; S P E C I A L D E V I C E H E A D E R
NEXT_DEV DD -1 ;POINTER TO NEXT DEVICE
ATTRIBUTE DW 2000H ;BLOCK DEVICE (NON-IBM FORMAT)
STRATEGY DW DEV_STRATEGY ;POINTER TO DEVICE STRATEGY
INTERRUPT DW DEV_INT ;POINTER TO DEVICE INTERRUPT HANDLER
DEV_NAME DB 1 ;NUMBER OF BLOCK DEVICES
DB 7 DUP (?) ;7 BYTES OF FILLER
;
RH_OFF DW ? ;REQUEST HEADER OFFSET
RH_SEG DW ? ;REQUEST HEADER SEGMENT
; BIOS PARAMETER BLOCK
BPB EQU $
DW 512 ;SECTOR SIZE
DB 2;(JS change) ;SECTOR/ALLOCATION UNIT
DW 1 ;NUMBER OF RESERVED SECTORS
DB 2 ;NUMBER OF FATS
DW 112;(JS change) ;NUMBER OF DIRECTORY ENTRIES
SECTCT1 DW ? ;TOTAL NUMBER OF SECTORS
DB 0FCH; ;MEDIA DESCRIPTOR
DW 2 ;NUMBER OF SECTORS OCCUPIED BY FAT
;
BPB_PTR DW BPB ;BIOS PARAMETER BLOCK POINTER ARRAY (1 ENTR)
; CURRENT VIRTUAL DISK INFORMATION
TOTAL DW ? ;TOTAL SECTORS TO TRANSFER
VERIFY DB 0 ;VERIFY 1=YES, 0=NO
START_SEC DW 0 ;STARTING SECTOR NUMBER
VDISK_PTR DW 0 ;STARTING SEGMENT OF VIRTUAL DISK
USER_DTA DD ? ;POINTER TO CALLSER DISK TRANSFER ADDRESS
BOOT_REC EQU $ ;DUMMY DOS BOOT RECORD
DB 3 DUP (0) ;3 BYTE JUMP TO BOOT CODE (NOT BOOTABLE)
DB 'IBM 2.0' ;VENDOR IDENTIFICATION
DW 512 ;NUMBER OF BYTES IN A SECTOR
DB 2;(JS change) ;1 SECTOR PER ALLOCATION UNIT
DW 1 ;1 RESERVED SECTOR
DB 2 ;2 FATS
DW 112;(JS change) ;NUMBER OF DIRECTORY ENTRIES
SECTCT2 DW ? ;TOTAL SECTORS IN IMAGE
DB 0FCH; ;TELLS DOS THIS IS A SINGLE SIDED 9 SECTOR
DW 2 ;NUMBER OF SECTORS IN FAT
;
; FUNCTION TABLE
;
FUNTAB LABEL BYTE
DW INIT ;INITIALIZATION
DW MEDIA_CHECK ;MEDIA CHECK (BLOCK ONLY)
DW BUILD_BPB ;BUILD BPB " "
DW IOCTL_IN ;IOCTL INPUT
DW INPUT ;INPUT (READ)
DW ND_INPUT ;NON_DESTRUCTIVE INPUT NO WAIT (CHAR ONLY)
DW IN_STAT ;INPUT STATUS (CHAR ONLY)
DW IN_FLUSH ;INPUT FLUSH " "
DW OUTPUT ;OUTPUT (WRITE)
DW OUT_VERIFY ;OUTPUT (WRITE) WITH VERIFY
DW OUT_STAT ;OUTPUT STATUS (CHAR ONLY)
DW OUT_FLUSH ;OUTPUT FLUSH " "
DW IOCTL_OUT ;IOCTL OUTPUT
;
; L O C A L P R O C E D U R E S
;
IN_SAVE PROC NEAR
MOV AX,ES:WORD PTR DTA[BX] ;SAVE CALLERS DTA
MOV CS:USER_DTA,AX
MOV AX,ES:WORD PTR DTA+2[BX]
MOV CS:USER_DTA+2,AX
MOV AX,ES:WORD PTR COUNT[BX] ;GET NUMBER OF SECTOR TO TOTAL
XOR AH,AH
MOV CS:TOTAL,AX ;MOVE NUMBER OF SECTORS TO TOTAL
RET
IN_SAVE ENDP
;
CALC_ADDR PROC NEAR
MOV AX,CS:START_SEC ;GET STARTING SECTOR NUMBER
MOV CX,20H ;MOV 512 TO CX SEGMENT STYLE
MUL CX ;MULTIPLY TO GET ACTUAL SECTOR
MOV DX,CS:VDISK_PTR ;GET SEGMENT OF VIRTUAL DISK
ADD DX,AX ;ADD THAT SEGMENT TO INITIAL SEGMENT
MOV DS,DX ;SAVE THAT AS THE ACTUAL SEGMENT
XOR SI,SI ;IT'S ON A PARAGRAPH BOUNDRY
MOV AX,CS:TOTAL ;TOTAL NUMBER OF SECTOR TO READ
MOV CX,512 ;BYTES PER SECTOR
MUL CX ;MULTIPLY TO GET COPY LENGTH
OR AX,AX ;CHECK FOR GREATER THAN 64K
JNZ MOVE_IT
MOV AX,0FFFFH ;MOVE IN FOR 64K
MOVE_IT:
XCHG CX,AX ;MOVE LENGTH TO CX
RET
CALC_ADDR ENDP
;
SECTOR_READ PROC NEAR
CALL CALC_ADDR ;CALCULATE THE STARTING 'SECTOR'
MOV ES,CS:USER_DTA+2 ;SET DESTINATION (ES:DI) TO POINT
MOV DI,CS:USER_DTA ;TO CALLERS DTA
;
; CHECK FOR DTA WRAP IN CASE WE CAME THROUGH VIA VERIFY
;
MOV AX,DI ;GET OFFSET OF DTA
ADD AX,CX ;ADD COPY LENGTH TO IT
JNC READ_COPY ;CARRY FLAG = 0, NO WRAP
MOV AX,0FFFFH ;MAX LENGTH
SUB AX,DI ;SUBTRACT DTA OFFSET FROM MAX
MOV CX,AX ;USE THAT AS COPY LENGTH TO AVOID WRAP
READ_COPY:
REP MOVSB ;DO THE 'READ'
RET
SECTOR_READ ENDP
;
SECTOR_WRITE PROC NEAR
CALL CALC_ADDR ;CALCULATE STARTING 'SECTOR'
PUSH DS
POP ES ;ESTABLISH ADDRESSABILITY
MOV DI,SI ; ES:DI POINT TO 'DISK`
MOV DS,CS:USER_DTA+2 ; DS:SI POINT TO CALLERS DTA
MOV SI,CS:USER_DTA
;
; CHECK FOR DTA WRAP
;
MOV AX,SI ;MOVE DTA OFFSET TO AX
ADD AX,CX ;ADD COPY LENGTH TO OFFSET
JNC WRITE_COPY ;CARRY FLAG = 0, NO SEGMENT WRAP
MOV AX,0FFFFH ;MOVE IN MAX COPY LENGTH
SUB AX,SI ;SUTRACT DTA OFFSET FROM MAX
MOV CX,AX ;USE AS NEW COPY LENGTH TO AVOID WRAP
WRITE_COPY:
REP MOVSB ;DO THE 'WRITE'
RET
SECTOR_WRITE ENDP
;
; D E V I C E S T R A T E G Y
;
DEV_STRATEGY:
MOV CS:RH_SEG,ES ;SAVE SEGMENT OF REQUEST HEADER POINTER
MOV CS:RH_OFF,BX ;SAVE OFFSET OF " "...
RET
;
; D E V I C E I N T E R R U P T H A N D L E R
;
DEV_INT:
; PRESERVE MACHINE STATE ON ENTRY
CLD
PUSH DS
PUSH ES
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSH SI
;
; DO THE BRANCH ACCORDING TO THE FUNCTION PASSED
;
MOV AL,ES:[BX]+2 ;GET FUNCTION BYTE
ROL AL,1 ;GET OFFSET INTO TABLE
LEA DI,FUNTAB ;GET ADDRESS OF FUNCTION TABLE
XOR AH,AH
ADD DI,AX
MOV BX,CS:RH_OFF ;See PC Age 2.6,
MOV ES,CS:RH_SEG ; p. 65. (JS)
JMP WORD PTR[DI]
;
; INIT
;
INIT:
PUSH CS
POP DX ;CURRENT CS TO DX
;
PUSH ES ;JS modification:
MOV AX,0 ; Load number of kilobytes
MOV ES,AX ; from last half of last
MOV AX,ES:3FEH ; "interrupt" slot, convert
SAL AX,1 ; to number of sectors,
MOV CS:SECTCT1,AX ; and store result.
MOV CS:SECTCT2,AX
POP ES
;
LEA AX,CS:VDISK ;GET ADDRESS OF VIRTUAL DISK
MOV CL,4
ROR AX,CL ;DIVIDE BY 16 (PARAGRAPH FORM)
ADD DX,AX ;ADD TO CURRENT CS VALUE
MOV CS:VDISK_PTR,DX ;SAVE AS STARTING SEGMENT OF VIRTUAL DISK
MOV AX,SECTCT1 ; ADD ENOUGH PARAGRAPHS TO STARTING
MOV CL,5 ; SEGMENT OF VIRTUAL DISK
SAL AX,CL
ADD DX,AX
MOV ES:WORD PTR BR_ADDR_0[BX],0
MOV ES:BR_ADDR_1[BX],DX ;MAKE THAT THE BREAK ADDRESS
MOV ES:BYTE PTR UNITS[BX],1 ;NUMBER OF DISKETTE UNITS
LEA DX,BPB_PTR ;GET ADDRESS OF BPB POINTER ARRAY
MOV ES:BPB_PTR_OFF[BX],DX ;SAVE OFFSET IN DATA PACKET
MOV ES:BPB_PTR_SEG[BX],CS ;SAVE SEGMENT IN DATA PACKET
MOV ES,CS:VDISK_PTR ;GET STARTING SECTOR OF VIRTUAL DISK
XOR DI,DI ;ZERO OUT DI (BOOT RECORD)
LEA SI,BOOT_REC ;ADDRESS OF BOOT RECORD
MOV CX,24
REP MOVSB ;COPY 24 BYTES OF BOOT RECORD
MOV CS:WORD PTR START_SEC,1
MOV CS:WORD PTR TOTAL,2
CALL CALC_ADDR ;CALCULATE ADDRESS OF LOGICAL SECTOR 1
PUSH DS
POP ES
MOV DI,SI ;MOVE THAT ADDRES TO ES:DI
XOR AL,AL
REP STOSB ;ZERO OUT FAT AREA
MOV DS:BYTE PTR [SI],0FCH ;SET THE FIRST FAT ENTRY
MOV DS:BYTE PTR 1[SI],0FFH
MOV DS:BYTE PTR 2[SI],0FFH
PUSH DS ;SAVE POINTER TO FAT
PUSH SI ; ON THE STACK
MOV CS:WORD PTR START_SEC,3
MOV CS:WORD PTR TOTAL,2
CALL CALC_ADDR ;CALCULATE ADDRESS OF LOGICAL SECTOR 3
PUSH DS
POP ES
MOV DI,SI ;MOVE THAT ADDRESS TO ES:DI
POP SI
POP DS ;RESTORE ADDRESS TO FIRST FAT
REP MOVSB ;COPY FIRST FAT TO SECOND FAT
MOV CS:WORD PTR START_SEC,5
MOV CS:WORD PTR TOTAL,7;(JS change)
CALL CALC_ADDR ;CALCULATE ADDR OF L.S. 5 (START OF DIR)
XOR AL,AL
PUSH DS
POP ES ;SET UP ES:DI TO POINT T
XOR DI,DI
REP STOSB ;ZERO OUT DIRECTORY
MOV ES,CS:RH_SEG ;RESTORE ES:BX TO REQUEST HEADER
MOV BX,CS:RH_OFF
STATUS DONE,NOERROR,0 ;SET STATUS WORD (DONE, NOERROR)
JMP EXIT
;
; MEDIA CHECK
;
MEDIA_CHECK: ;MEDIA CHECK (BLOCK ONLY)
;
; SET MEDIA NOT CHANGED
;
MOV ES:BYTE PTR RET_BYTE[BX],1 ;STORE IN RETURN BYTE
STATUS DONE,NOERROR,0
JMP EXIT
;
; BUILD BIOS PARAMETER BLOCK
;
BUILD_BPB:
PUSH ES ;SAVE SRH SEGMENT
PUSH BX ;SAVE SRH OFFSET
MOV CS:WORD PTR START_SEC,0
MOV CS:WORD PTR TOTAL,1
CALL CALC_ADDR
PUSH CS
POP ES
LEA DI,BPB ;ADDRESS OF BIOS PARAMETER BLOCK
ADD SI,11 ;ADD 11 TO SI
MOV CX,13 ;LENGTH OF BPB
REP MOVSB
POP BX ;RESTORE OFFSET OF SRH
POP ES ;RESTORE SEGMENT OF SRH
LEA DX,BPB ;GET BPB ARRAY POINTER
MOV ES:BPBA_PTR[BX],DX ;SAVE PTR TO BPB TABLE
MOV ES:BPBA_PTR+2[BX],CS
MOV ES:DTA[BX],DX ;OFFSET OF SECTOR BUFFER
MOV ES:DTA+2[BX],CS
STATUS DONE,NOERROR,0
JMP EXIT
;
; THE FOLLOWING ENTRIES ARE FOR NOT SUPPORTED BY THIS DEVICE
;
IOCTL_IN:
IOCTL_OUT:
ND_INPUT: ;NON_DESTRUCTIVE INPUT NO WAIT (CHAR ONLY)
IN_STAT: ;INPUT STATUS " "....
IN_FLUSH: ;INPUT FLUSH " "....
OUT_STAT: ;OUTPUT STATUS" "....
OUT_FLUSH: ;OUTPUT FLUSH " "....
;
; DISK READ
;
INPUT:
CALL IN_SAVE ;CALL THE INITIAL SAVE ROUTINE
MOV AX,ES:WORD PTR SSN[BX] ;SET STARTING SECTOR NUMBER
MOV CS:START_SEC,AX ;SAVE STARTING SECTOR NUMBER
MOV AX,ES:WORD PTR COUNT[BX]
MOV CS:TOTAL,AX ;SAVE TOTAL SECTORS TO TRANSFER
CALL SECTOR_READ ;READ IN THAT MANY SECTORS
MOV BX,CS:RH_OFF ;RESTORE ES:BX AS REQUEST HEADER POINTER
MOV ES,CS:RH_SEG
STATUS DONE,NOERROR,0
JMP EXIT
;
; DISK WRITE
;
OUTPUT: ;OUTPUT (WRITE)
CALL IN_SAVE
MOV AX,ES:WORD PTR SSN[BX] ;GET STARTING SECTOR NUMBER
MOV CS:START_SEC,AX ;SET " "......
MOV AX,ES:WORD PTR COUNT[BX]
MOV CS:TOTAL,AX ;SAVE TOTAL SECTORS TO WRITE
CALL SECTOR_WRITE ;WRITE OUT THOSE SECTORS
MOV BX,CS:RH_OFF ;RESTORE ES:BX AS REQUEST HEADER POINTER
MOV ES,CS:RH_SEG
CMP CS:BYTE PTR VERIFY,0 ;WRITE VERIFY SET
JZ NO_VERIFY ;NO, NO WRITE VERIFY
MOV CS:BYTE PTR VERIFY,0 ;RESET VERIFY INDICATOR
JMP INPUT ;READ THOSE SECTORS BACK IN
NO_VERIFY:
STATUS DONE,NOERROR,0 ;SET DONE, NO EROR IN STATUS WORD
JMP EXIT
OUT_VERIFY: ;OUTPUT (WRITE) WITH VERIFY
MOV CS:BYTE PTR VERIFY,1 ;SET THE VERIFY FLAG
JMP OUTPUT ;BRANCH TO OUTPUT ROUTINE
;
; COMMON EXIT
;
EXIT:
POP SI ;RESTORE ALL OF THE REGISTERS
POP DI
POP DX
POP CX
POP BX
POP AX
POP ES
POP DS
RET
E_O_P:
; MACRO TO ALIGN THE VIRTUAL DISK ON A PARAGRAPH BOUNDARY
IF ($-START) MOD 16
ORG ($-START)+16-(($-START) MOD 16)
ENDIF
VDISK EQU $
VDSK ENDP
CSEG ENDS
END BEGIN