home *** CD-ROM | disk | FTP | other *** search
- ;
- ; ReSizeable RAMDisk device driver for XMS memory
- ; Version 1.20
- ;
- ; May be compiled with either MASM or TASM
- ;
- ; Released to PUBLIC DOMAIN by author Marko Kohtala 1991
- ;
- ; Some documentation available in accompanying file SRDISK.DOC.
- ; If not, contact author by sending E-mail from
- ;
- ; Internet, Bitnet etc. to 'mkohtala@niksula.hut.fi'
- ; CompuServe to '>INTERNET:mkohtala@niksula.hut.fi'
- ;
- ; or by calling Airline QBBS, 24H, HST, V.32, V.42, MNP,
- ; +358-0-8725380, and leaving mail to me, Marko Kohtala.
- ;
- ; History:
- ; 1.00 Initial release
- ; 1.10 Added into IOCTL_msg media_change byte, that must be changed to
- ; -1 by srdisk if media changed. Changed header version to SRD 1.10.
- ; 1.20 Fixed name of program by adding the missing 'Re' to 'Sizeable'.
- ; Upgraded IOCTL_msg_s to version 1.20 by adding byte to tell usable
- ; memory types.
- ; Updated to work with DOS versions 2.x-5.x - not tested.
-
- .286c
- d_seg segment para public
- assume ds:d_seg, cs:d_seg
-
- org 0
- ; Device driver header
- dd -1 ; Pointer to next device (now last)
- dw 4800h ; Support for IOCTL and removable media calls
- dw offset strategy ; Offset to strategy function
- dw offset commands ; Offset to commands function
- db 1 ; Number of units
-
- ; Pointers to commands
- command_tbl dw cmd_init ; 0
- dw cmd_media ; 1
- dw cmd_BPB ; 2
- dw cmd_I_IOCTL ; 3
- dw cmd_input ; 4
- dw cmd_ok ; 5
- dw cmd_ok ; 6
- dw cmd_ok ; 7
- dw cmd_output ; 8
- dw cmd_output ; 9 With verify
- dw cmd_ok ; 10
- dw cmd_ok ; 11
- dw cmd_O_IOCTL ; 12
- dw cmd_open ; 13
- dw cmd_close ; 14
- dw cmd_removable ; 15
-
-
- ;**************************************************************************
- ;
- ; IOCTL message structure
- ;
- ; This structure is the data packet exchanged between this device
- ; driver and the RAM disk formatter program. The formatter will first
- ; read this structure and verify the version of the message structure,
- ; then it will make any necessary modifications to it and send it back.
- ;
- ; !!! The formatter will use any initial values in this structure as
- ; default values i.e. set all needed values here !!!
- ;**************************************************************************
-
- READ_ACCESS equ 1 ; Bit masks for the RW_access
- WRITE_ACCESS equ 2
-
- XMS_MEMORY equ 1 ; Different memory types supported bit masks
- EMS_MEMORY equ 2
- CONV_MEMORY equ 4
- BSW_MEMORY equ 8
-
- IOCTL_msg_s struc
- dw type IOCTL_msg_s ; Length of the structure
- db 90h ; Makes this look like boot record
- db 'SRD 1.20' ; IOCTL_msg structure version
-
- ; BIOS Parameter Block structure
- bytes_per_sector dw 128 ; Smallest sector size
- sectors_per_cluster db 4 ; Cluster size 4*128 = 512
- reserved_sec dw 1 ; The boot sector is reserved
- FATs db 1 ; One FAT copy
- dir_entries dw 64 ; 64 entries in root directory
- sectors dw ? ; Total number of sectors on disk
- media db 0FAh ; Media is RAM DISK
- FAT_sectors dw ? ; Sectors per one FAT
- ; Internal data
- disk_size dw 0 ; Disk size in K-bytes (0 at start)
- volume db 'SRDISK ', 0 ; ASCIIZ string of volume label
- RW_access db 00b ; B0 = read, B1 = write (disabled now)
- media_change db 1 ; -1 if media changed, 1 if not
-
- ; These are not accepted from outside
- open_files dw 0 ; Files currently open on drive
- IO_entry_off dw ? ; External entry to disk_IO
- IO_entry_seg dw ?
- memory_type db XMS_MEMORY ; This driver uses XMS memory
- IOCTL_msg_s ends
-
- O_IOCTL_msg_len equ open_files ; Number of bytes we accept from outside
-
- ; Because of Bugs in TASM we must put 'type ...' here too
- IOCTL_msg IOCTL_msg_s <type IOCTL_msg_s,,,,,,,,,,,,,,,,offset far_disk_IO>
-
- ;**************************************************************************
- ;
- ; Local data
- ;
- ;**************************************************************************
-
- BPB equ byte ptr IOCTL_msg.bytes_per_sector
- pBPB dw offset BPB ; Pointer to BPB (for cmd_init)
-
- req_ptr dd ? ; Request structure pointer
-
- XMS_entry dd ? ; XMS driver entry point
- XMS_handle dw -1 ; XMS handle to disk memory
- XMS_cblk db 16 dup (0) ; XMS move command data structure
-
-
- ;**************************************************************************
- ;
- ; Set request header address
- ;
- ; Called by DOS to set the request structure pointer
- ;
- ;**************************************************************************
-
- strategy proc far
- mov word ptr cs:req_ptr,bx
- mov word ptr cs:req_ptr+2,es
- retf ; Return far
- strategy endp
-
-
- ;**************************************************************************
- ;
- ; Commands
- ;
- ; Called by DOS. Requested action defined in structure pointed by req_ptr.
- ;
- ;**************************************************************************
-
- commands proc far
- push ax
- push bx
- push cx
- push dx
- push si
- push di
- push ds
- push es
- lds si,cs:req_ptr
- ; We trust Microsoft that the unit is right at [req_ptr]+1
- mov cx,[si+12h] ; Sectors/Cmd line/BPB pointer
- mov dx,[si+14h] ; Start sector/Device number
- mov bl,[si+2] ; Command
- cmp bl,0Fh ; Is command supported?
- ja cmd_unknown ; Jump if not
- xor bh,bh ; Count index to command_tbl
- shl bx,1
- les di,dword ptr [si+0Eh] ; ES:DI = transfer address
- push cs
- pop ds ; DS to local data segment
- jmp word ptr [command_tbl+bx] ; Do command
- cmd_unknown:
- mov al,3
- jmp cmd_error
- cmd_IOerr:
- lds bx,cs:req_ptr
- mov word ptr [bx+12h],0 ; Sector count zero
- cmd_error:
- mov ah,81h ; ERROR and DONE
- jmp cmd_ret
-
- cmd_removable: ; Enough to return DONE without BUSY flag set
- cmd_ok:
- mov ah,1 ; DONE
- cmd_ret:
- lds bx,cs:req_ptr
- mov [bx+3],ax ; save status
- pop es
- pop ds
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- retf ; Return far
- commands endp
-
-
- ;**************************************************************************
- ;
- ; Media Check command
- ;
- ;**************************************************************************
-
- cmd_media proc near
- les bx,req_ptr
-
- mov ax,100h ; DONE status
- mov dh,IOCTL_msg.media_change ; Read the change return
-
- test IOCTL_msg.RW_access,READ_ACCESS
- jnz cmd_media1
- mov ax,8102h ; "Device not ready" status
- mov dh,-1 ; "Changed"
- cmd_media1:
- mov es:[bx+0Eh],dh
- mov word ptr es:[bx+0Fh],offset volume
- mov es:[bx+11h],cs
- jmp cmd_ret
- cmd_media endp
-
-
- ;**************************************************************************
- ;
- ; Build BPB command
- ;
- ;**************************************************************************
-
- cmd_BPB proc near
- les bx,req_ptr
- mov word ptr es:[bx+12h],offset BPB
- mov es:[bx+14h],cs
- mov IOCTL_msg.open_files,0 ; Reset open files to 0
- mov IOCTL_msg.media_change,1 ; Media not changed
- test IOCTL_msg.RW_access,READ_ACCESS
- jz cmd_BPB1
- jmp cmd_ok
- cmd_BPB1:
- mov al,2 ; "Device not ready"
- jmp cmd_error
- cmd_BPB endp
-
-
- ;**************************************************************************
- ;
- ; Device Open command
- ;
- ;**************************************************************************
-
- cmd_open proc near
- inc IOCTL_msg.open_files
- jmp cmd_ok
- cmd_open endp
-
-
- ;**************************************************************************
- ;
- ; Device Close command
- ;
- ;**************************************************************************
-
- cmd_close proc near
- cmp IOCTL_msg.open_files,0
- jz cmd_close1
- dec IOCTL_msg.open_files
- cmd_close1:
- jmp cmd_ok
- cmd_close endp
-
-
- ;**************************************************************************
- ;
- ; INPUT command
- ;
- ;**************************************************************************
-
- cmd_input proc near
- test IOCTL_msg.RW_access,READ_ACCESS
- jz cmd_input1
- xor bh,bh
- jmp cmd_io
- cmd_input1:
- mov al,2 ; "Device not ready"
- jmp cmd_IOerr
- cmd_input endp
-
-
- ;**************************************************************************
- ;
- ; OUTPUT command
- ;
- ;**************************************************************************
-
- cmd_output proc near
- test IOCTL_msg.RW_access,WRITE_ACCESS
- jz cmd_output1
- mov bh,1
- cmd_io:
- call disk_IO
- jc cmd_output2 ; Jump if error
- jmp cmd_ok
- cmd_output1:
- mov al,0 ; "Write protect violation"
- cmd_output2:
- jmp cmd_IOerr
- cmd_output endp
-
-
- ;**************************************************************************
- ;
- ; I/O ROUTINE TO THE RAM DISK
- ;
- ; On entry
- ; bh - 0 then read, else write
- ; cx - number of sectors
- ; dx - starting sector
- ; es:di - transfer buffer
- ;
- ; Return
- ; - carry clear if no error
- ; - carry set and error code in al
- ;
- ;**************************************************************************
-
- IO_err:
- mov al,8 ; "Sector not found"
- stc ; Set carry flag
- retn
-
- disk_IO proc near
- cmp dx,IOCTL_msg.sectors ; Startting sector on disk?
- jae IO_err ; Jump if not
- mov ax,dx ; Count ending sector
- add ax,cx
- cmp ax,IOCTL_msg.sectors ; Ending sector on disk?
- ja IO_err ; Jump if not
- mov si,offset XMS_cblk
- push dx
- mov ax,cx ; Count number of words to move
- mul IOCTL_msg.bytes_per_sector
- jnc disk_IO1 ; Jump if not too much
-
- push ds ; -- Make moved block shorter
- push bx ; and count the sectors
- mov ax,0F000h ; 0F000h should divide with
- push ax
- div IOCTL_msg.bytes_per_sector ; every bytes_per_sector
- lds bx,req_ptr
- mov [bx+12h],ax ; Report right sector count
- pop ax
- pop bx
- pop ds
- disk_IO1:
- mov [si],ax ; Number of bytes to move
- mov word ptr [si+2],0
-
- pop ax ; Pushed as dx, start sector
- mul IOCTL_msg.bytes_per_sector ; dx:ax = the starting byte
-
- or bh,bh ; Input/output?
- mov bx,XMS_handle
- jnz disk_IO2 ; Jump if write
- ; -- Read
- mov [si+4],bx ; Source in XMS
- mov [si+6],ax
- mov [si+8],dx
- mov word ptr [si+0Ah],0 ; Destination in main memory
- mov [si+0Ch],di
- mov [si+0Eh],es
- jmp disk_IO3
- disk_IO2: ; -- Write
- mov word ptr [si+4],0 ; Source in main memory
- mov [si+6],di
- mov [si+8],es
- mov [si+0Ah],bx ; Destination in XMS
- mov [si+0Ch],ax
- mov [si+0Eh],dx
- disk_IO3:
- mov ah,0Bh ; Move XMS block
- call XMS_entry
- shr ax,1
- cmc ; Carry set if err
- jnc disk_IO_ret
- mov al,0Ch ; "General failure"
- disk_IO_ret:
- ret
- disk_IO endp
-
-
- ;**************************************************************************
- ;
- ; EXTERNAL I/O ROUTINE TO THE RAM DISK
- ;
- ; On entry
- ; bh - 0 then read, else write
- ; cx - number of sectors
- ; dx - starting sector
- ; es:di - transfer buffer
- ;
- ; Return in ax: 0 for success, 1 for failure
- ;
- ;**************************************************************************
-
- far_disk_IO proc far
- push ds
- push si
- push di
- push cs ; Switch to local data segment
- pop ds
- call disk_IO
- xor ax,ax
- jnc far_disk_IO1
- inc ax
- far_disk_IO1:
- pop di
- pop si
- pop ds
- ret
- far_disk_IO endp
-
-
- ;**************************************************************************
- ;
- ; IOCTL Read - send configuration
- ;
- ;**************************************************************************
-
- cmd_I_IOCTL proc near
- cmp cx,type IOCTL_msg_s ; Requested too much?
- jna cmd_I1
-
- mov cx,type IOCTL_msg_s ; Yes, send less than asked
- push ds
- lds bx,req_ptr
- mov [bx+12h],cx
- pop ds
- cmd_I1:
- mov si,offset IOCTL_msg
- rep movsb
- jmp cmd_ok
- cmd_I_IOCTL endp
-
-
- ;**************************************************************************
- ;
- ; IOCTL Write - receive new configuration
- ;
- ;**************************************************************************
-
- cmd_O_IOCTL proc near
- cmp cx,type IOCTL_msg_s ; Validate the length
- jne cmd_O_abort
-
- push di ; Validate the header
- mov si,offset IOCTL_msg
- mov cx,11
- repe cmpsb
- pop si
- jne cmd_O_abort
-
- cmp es:[si].media_change,1 ; See if no media change
- je cmd_O1 ; If not, no change in the disk
-
- mov IOCTL_msg.open_files,0 ; No open files, if media change
- mov bx,es:[si].disk_size ; See if disk size change
- cmp bx,IOCTL_msg.disk_size
- je cmd_O1
-
- mov dx,XMS_handle ; Change XMS disk size
- mov ah,0Fh
- call XMS_entry
- or ax,ax
- jz cmd_O_fail ; Report that failed
- cmd_O1:
- mov di,offset IOCTL_msg ; Read it
- mov cx,O_IOCTL_msg_len ; Exclude the tail
- push ds ; Swap es<->ds
- push es
- pop ds
- pop es
- rep movsb ; Write the internal table
- jmp cmd_ok
-
- cmd_O_abort: mov al,0Ah ; "Write fault"
- jmp cmd_IOerr
-
- cmd_O_fail: mov al,0Ch ; "General failure"
- jmp cmd_IOerr
-
- cmd_O_IOCTL endp
-
-
- ;**************************************************************************
- ;
- ; Warm Boot of Machine
- ;
- ; Release used XMS memory.
- ;
- ; I guess this may be important if some virtual machine (VM) in some
- ; multitasking system has installed this driver and the VM is ended.
- ; Without this the other VMs would loose the space reserved for RAM disk
- ; in this VM.
- ;**************************************************************************
-
- old_int19 label dword ; Address of old INT 19
- old_int19_off dw -1
- old_int19_seg dw -1
-
- int_19_entry proc far
- pusha
- mov dx,cs:XMS_handle
- cmp dx,-1
- je int19_1 ; Jump if no XMS handle
- mov ah,0Dh
- call cs:XMS_entry ; Unlock XMS memory
- mov ah,0Ah
- call cs:XMS_entry ; Free XMS memory
- int19_1:
- xor ax,ax
- mov ds,ax
- mov ax,cs:old_int19_off
- cli ; Disable interrupts
- mov ds:[19h*4],ax ; for the time to write
- mov ax,cs:old_int19_seg ; old interrupt vector back
- mov ds:[19h*4+2],ax
- popa ; Enable interrupts
- jmp cs:old_int19
- int_19_entry endp
-
-
- end_of_resident label byte ; MARKS THE END OF RESIDENT PORTION OF DRIVER
-
-
- ;**************************************************************************
- ;
- ; prints macro
- ;
- ; This macro is used by initialization routines to display text.
- ; dx must point to the '$' terminated text about to be displayed.
- ;**************************************************************************
-
- prints macro
- mov ah,9
- int 21h
- endm
-
-
- ;**************************************************************************
- ;
- ; INIT command
- ;
- ; Init command does the following:
- ; - checks DOS version. This driver is built in a way that requires
- ; at least dos version 3.00. I'm not sure wether even that is enough.
- ; - displays sign-on message (must display it after DOS version check
- ; because older versions do not report the drive)
- ; - initialize XMS to 0K disk
- ; - hook INT 19 bootstrap interrupt
- ; - fills in the request header
- ;**************************************************************************
-
- cmd_init proc near
- mov ah,30h
- int 21h ; Get DOS version number
-
- xchg ah,al
- cmp ax,200h
- jb cmd_init1
- cmp ax,600h
- jb cmd_init2
- cmd_init1:
- mov dx,offset errs_eDOS
- jmp cmd_init_err
- cmd_init2:
- les si,req_ptr
- cmp byte ptr es:[si],16h ; Device number supported?
- ja cmd_init4 ; Yes, use it
-
- mov s_vdisk,'$' ; Do not display "Virtual disk"
- jmp cmd_init5
- cmd_init4:
- mov al,es:[si+16h] ; Get drive number
- add s_drive,al ; and insert it to the string
-
- cmd_init5: mov dx,offset s_sign_on ; "Microsoft RAMdrive ver..."
- prints
-
- call init_XMS
- jc cmd_init_abort
-
- call set_int19
-
- mov IOCTL_msg.IO_entry_seg,cs
-
- mov al,1 ; One drive installed
- lds bx,req_ptr
- mov [bx+0Dh],al ; Save number of drives
- mov word ptr [bx+0Eh],offset end_of_resident
- cmd_init3:
- mov [bx+10h],cs
- mov word ptr [bx+12h],offset pBPB
- mov [bx+14h],cs
- jmp cmd_ok
-
- cmd_init_err:
- prints
- cmd_init_abort:
- lds bx,req_ptr
- xor ax,ax
- mov [bx+0Dh],al ; Zero the number of drives
- mov [bx+0Eh],ax
- jmp cmd_init3
-
- cmd_init endp
-
-
- ;**************************************************************************
- ;
- ; INT 19 hooking
- ;
- ; INT 19 is the bootstrap loader interrupt, which is invoked when user
- ; presses Ctrl-Alt-Del. We must hook it in order to release the
- ; extended memory allocated for RAM disk.
- ;**************************************************************************
-
- set_int19 proc near
- push ax
- push dx
- push bx
- push es
- mov ax,3519h
- int 21h ; Get old int 19 handler
- mov old_int19_off,bx
- mov old_int19_seg,es
- mov dx,offset int_19_entry
- mov ax,2519h
- int 21h ; Set new int 19 handler
-
- pop es
- pop bx
- pop dx
- pop ax
- retn
- set_int19 endp
-
-
- ;**************************************************************************
- ;
- ; XMS memory initialization
- ;
- ; Gets XMS server entry address and allocates 0K to get a memory handle
- ; for RAM disk
- ;
- ; Returns
- ; carry set if error
- ;**************************************************************************
-
- init_XMS proc near
- push es
- mov ax,4300h
- int 2Fh ; Get XMS installed status
- cmp al,80h
- jne init_XMS1 ; Jump if not installed
- mov ax,4310h
- int 2Fh ; Get XMS entry point
- jnc init_XMS2 ; Jump if no error
- init_XMS1:
- mov dx,offset errs_noXMS ; "No extended mem driver"
- jmp init_XMS4
- init_XMS2:
- mov word ptr XMS_entry,bx
- mov word ptr XMS_entry+2,es
- xor dx,dx ; Allocate 0K to get a handle
- mov ah,9
- call XMS_entry
- or ax,ax
- jz init_XMS3 ; Zero for failure
- mov XMS_handle,dx
- clc
- jmp init_XMS_ret
- init_XMS3:
- mov dx,offset errs_ealloc ; "Error in ext mem alloc"
- init_XMS4:
- prints
- stc
- init_XMS_ret:
- pop es
- ret
- init_XMS endp
-
-
- ;**************************************************************************
- ;
- ; Initialization strings
- ;
- ;**************************************************************************
-
- errs_noXMS db 'RAMDisk: Extended Memory Manager not present'
- db 0Dh, 0Ah, '$'
- errs_ealloc db 'RAMDisk: Error in extended memory allocation'
- db 0Dh, 0Ah, '$'
- errs_eDOS db 'RAMDisk: Incorrect DOS version'
- db 0Dh, 0Ah, '$'
- s_sign_on db 0Dh, 0Ah, 'ReSizeable RAMDisk (XMS) version 1.20, '
- db 'PUBLIC DOMAIN, 1991'
- db 0Dh, 0Ah
- s_vdisk db 'Virtual disk '
- s_drive db 'A:', 0Dh, 0Ah
- db 0Dh, 0Ah, '$'
-
-
- ;**************************************************************************
- ;
- ; A note for binary debuggers
- ;
- ;**************************************************************************
-
- db "Released to PUBLIC DOMAIN by author Marko Kohtala 1991. "
- db "Contact from Internet, Bitnet etc. to 'mkohtala@niksula.hut.fi', "
- db "CompuServe to '>INTERNET:mkohtala@niksula.hut.fi'"
-
-
- d_seg ends
- end
-