home *** CD-ROM | disk | FTP | other *** search
- ;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
-