add directory distributions
This commit is contained in:
879
distributions/TAMU/dos_utils/rawfd.asm
Normal file
879
distributions/TAMU/dos_utils/rawfd.asm
Normal file
@@ -0,0 +1,879 @@
|
||||
;*********************************************************************;
|
||||
;* rawfd.asm - a raw floppy device driver for MS-LOSS *;
|
||||
;* *;
|
||||
;* written by david safford (dave.safford@net.tamu.edu) *;
|
||||
;* portions of this code were derived from: *;
|
||||
;* condrv.asm by Michael Tischer (overall skeleton) *;
|
||||
;* drvload by Rick Knoblaugh (exe based loading) *;
|
||||
;* tapedriver by Brian Antoine (raw device open trap) *;
|
||||
;* *;
|
||||
;* Assembly: TASM rawfd *;
|
||||
;* LINK rawfd *;
|
||||
;* *;
|
||||
;* Usage: add "device=rawfd.exe" to config.sys and reboot, *;
|
||||
;* or load the driver directly with "rawfd". *;
|
||||
;* This will create devices "rawfda" and "rawfdb" for *;
|
||||
;* drives a and b respectively. The driver gets initial *;
|
||||
;* drive type information from bios. All data sent to *;
|
||||
;* the raw drives is simply streamed out to floppy one *;
|
||||
;* track at a time. If less than a track is written, *;
|
||||
;* it is held indefinitely until more data is sent, *;
|
||||
;* until the device is closed, or until the flush *;
|
||||
;* ioctl is sent (by rerunning rawfd.exe). *;
|
||||
;* If the driver is already loaded, subsequent invocations *;
|
||||
;* will send any command line options to the driver *;
|
||||
;* via ioctl. Command switches include 'f' (format), 'n' *;
|
||||
;* (no format), and 'r' (reset). *;
|
||||
;* *;
|
||||
;*********************************************************************;
|
||||
|
||||
code segment
|
||||
assume cs:code,ds:code
|
||||
org 0
|
||||
|
||||
;=====================================================================
|
||||
;Driver section
|
||||
|
||||
;---------------------------------------------------------------------;
|
||||
; header rawfda
|
||||
|
||||
hdr_a dw offset hdr_b ;well documented (:-) way to link to
|
||||
dw 0 ;hdr_b
|
||||
dw 1110100000000000b ;Driver attribute
|
||||
dw offset strata ;Pointer to strategy routine
|
||||
dw offset intr ;Pointer to interrupt routine
|
||||
db "RAWFDA " ;Raw Floppy driver
|
||||
|
||||
;---------------------------------------------------------------------;
|
||||
; header rawfdb
|
||||
|
||||
hdr_b dw -1,-1 ;end of driver chain
|
||||
dw 1110100000000000b ;Driver attribute
|
||||
dw offset stratb ;Pointer to strategy routine
|
||||
dw offset intr ;Pointer to interrupt routine
|
||||
db "RAWFDB " ;Raw Floppy driver
|
||||
|
||||
;---------------------------------------------------------------------;
|
||||
; driver function pointer table
|
||||
|
||||
fct_tab dw offset init ;Function 0: Initialization
|
||||
dw offset dummy ;Function 1: Media check
|
||||
dw offset dummy ;Function 2: Create BPB
|
||||
dw offset no_sup ;Function 3: I/O control read
|
||||
dw offset dummy ;Function 4: Read
|
||||
dw offset dummy ;Function 5: Non-destructive read
|
||||
dw offset dummy ;Function 6: Input status
|
||||
dw offset dummy ;Function 7: Delete input buffer
|
||||
dw offset write ;Function 8: Write
|
||||
dw offset write ;Function 9: Write & verify
|
||||
dw offset dummy ;Function 10: Output status
|
||||
dw offset flush ;Function 11: Delete output buffer
|
||||
dw offset ioc_wr ;Function 12: I/O control write
|
||||
dw offset open ;Function 13: Open (Ver. 3.0 and up)
|
||||
dw offset close ;Function 14: Close
|
||||
dw offset dummy ;Function 15: Changeable medium
|
||||
dw offset write ;Function 16: Output until busy
|
||||
|
||||
;---------------------------------------------------------------------;
|
||||
; driver equates and data
|
||||
|
||||
cmd_fld equ 2 ;Offset command in req header
|
||||
status equ 3 ;Offset status in req header
|
||||
end_adr equ 14 ;Offset driver end adr in req header
|
||||
num_db equ 18 ;Offset number in req header
|
||||
b_adr equ 14 ;Offset buf address in req header
|
||||
|
||||
NUM_SEC_4 equ 18 ;type 4 diskette (1.44M)
|
||||
NUM_SEC_2 equ 15 ;type 2 diskette (1.2M)
|
||||
BUF_SZ_4 equ 512*18 ;Size of track buf for type 4 (1.44)
|
||||
BUF_SZ_2 equ 512*15 ;size of track buf for type 2 (1.2)
|
||||
num_cmd equ 16 ;Subfunctions 0-16 are supported
|
||||
|
||||
|
||||
db_ptr dw (?),(?) ;Address of req header
|
||||
buf_start dw (?) ;offset to active track buffer
|
||||
buf_end dw (?) ;offset to end of buffer
|
||||
fmt db 18*4 dup (?) ;format track data buffer
|
||||
|
||||
num_cyl db 80
|
||||
num_head db 2
|
||||
num_sec_a db NUM_SEC_4
|
||||
buf_sz_a dw BUF_SZ_4
|
||||
num_sec_b db NUM_SEC_2
|
||||
buf_sz_b dw BUF_SZ_2
|
||||
|
||||
do_format db 1
|
||||
cur_count dw 0
|
||||
cur_drive db 0
|
||||
cur_num_sec db NUM_SEC_4
|
||||
cur_buf_sz dw BUF_SZ_4
|
||||
cur_cyl db 0
|
||||
cur_head db 0
|
||||
tries db 0
|
||||
req_num dw 0
|
||||
req_dec dw 0
|
||||
req_off dw 0
|
||||
req_seg dw 0
|
||||
init_done db 0
|
||||
|
||||
;---------------------------------------------------------------------;
|
||||
; driver a strategy
|
||||
|
||||
strata proc far ;Strategy routine
|
||||
|
||||
mov cs:db_ptr,bx ;Store address of req header in the
|
||||
mov cs:db_ptr+2,es ;Variable DB_PTR
|
||||
mov cs:cur_drive,0 ;let writer know logical device
|
||||
mov ah,cs:num_sec_a ;update cur parameters
|
||||
mov cs:cur_num_sec,ah
|
||||
mov ax,cs:buf_sz_a
|
||||
mov cs:cur_buf_sz,ax
|
||||
|
||||
ret ;Return to caller
|
||||
|
||||
strata endp
|
||||
|
||||
;---------------------------------------------------------------------;
|
||||
;driver b strategy
|
||||
|
||||
stratb proc far ;Strategy routine
|
||||
|
||||
mov cs:db_ptr,bx ;Store address of req header in
|
||||
mov cs:db_ptr+2,es ;the Variable DB_PTR
|
||||
mov cs:cur_drive,1 ;let writer know logical device
|
||||
mov ah,cs:num_sec_b ;update cur drive parameters
|
||||
mov cs:cur_num_sec,ah
|
||||
mov ax,cs:buf_sz_b
|
||||
mov cs:cur_buf_sz,ax
|
||||
|
||||
ret ;Return to caller
|
||||
|
||||
stratb endp
|
||||
|
||||
;---------------------------------------------------------------------;
|
||||
; driver interrupt code
|
||||
|
||||
intr proc far ;Interrupt routine
|
||||
|
||||
push ax ;Push registers onto the stack
|
||||
push bx
|
||||
push cx
|
||||
push dx
|
||||
push di
|
||||
push si
|
||||
push bp
|
||||
push ds
|
||||
push es
|
||||
pushf ;Push flag register onto the stack
|
||||
|
||||
push cs ;Set data segment register
|
||||
pop ds ;Code and data are identical
|
||||
|
||||
les di,dword ptr db_ptr ;Address of data req header to ES:DI
|
||||
mov bl,es:[di+cmd_fld] ;Get command code
|
||||
cmp bl,num_cmd ;is command code permitted?
|
||||
jle bc_ok ;YES --> bc_ok
|
||||
|
||||
mov ax,8003h ;Code for "Unknown command"
|
||||
jmp short intr_end ;Return to caller
|
||||
|
||||
bc_ok: shl bl,1 ;Calculate pointer in jump table
|
||||
xor bh,bh ;Clear BH
|
||||
call [fct_tab+bx] ;Call function
|
||||
les di,dword ptr cs:db_ptr ;req header address to ES:DI
|
||||
|
||||
intr_end label near
|
||||
or ax,0100h ;Set ready bit
|
||||
mov es:[di+status],ax ;Store everything in the status field
|
||||
|
||||
popf ;Restore flag register
|
||||
pop es ;Restore other registers
|
||||
pop ds
|
||||
pop bp
|
||||
pop si
|
||||
pop di
|
||||
pop dx
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
|
||||
ret ;Return to caller
|
||||
|
||||
intr endp
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; dummy (no error) routine
|
||||
|
||||
dummy proc near ;This routine does nothing
|
||||
|
||||
xor ax,ax ;Clear busy bit
|
||||
ret ;Return to caller
|
||||
|
||||
dummy endp
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; dummy (returns error) routine
|
||||
|
||||
no_sup proc near ;for all functions
|
||||
;which should not be called
|
||||
mov ax,8003h ;Error: Command not recognized
|
||||
ret ;Return to caller
|
||||
|
||||
no_sup endp
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
;write: simply buffer chars until have a full track.
|
||||
|
||||
write proc near
|
||||
|
||||
;this is a pain in asm -- have to handle case of
|
||||
;request larger, smaller, or equal to that available in buffer.
|
||||
|
||||
;move original request info to working variables
|
||||
mov cx, es:[di+num_db] ;Number of source characters
|
||||
mov cs:req_num, cx ;working pointer to source data
|
||||
mov ax, es:[di+b_adr]
|
||||
mov cs:req_off, ax
|
||||
mov ax, es:[di+b_adr+2]
|
||||
mov cs:req_seg, ax
|
||||
|
||||
write_s: ; set up copy of data to buffer: want ds:si -> es:di
|
||||
; for cx count, LIMITED by buf length and any current contents
|
||||
|
||||
;check that we have something to put in buffer
|
||||
mov cx, cs:req_num
|
||||
jcxz write_e
|
||||
|
||||
;calculate di (destination offset)
|
||||
mov ax, cs:buf_start ;get start of buf
|
||||
add ax, cs:cur_count ;add offset for already queued data
|
||||
mov di,ax
|
||||
|
||||
;calculate cx (count for this loop)
|
||||
mov ax, cs:cur_buf_sz ;how big is buf
|
||||
sub ax, cs:cur_count ;minus queued data -> available
|
||||
cmp ax, cx ;num left to write
|
||||
jnb write_a ;fits within buf
|
||||
mov cx,ax ;data too big, so limit to buf space
|
||||
;cx now has num to write this time
|
||||
|
||||
write_a: mov cs:req_dec,cx ;save this decrement count
|
||||
mov ds,cs:req_seg ;point ds to source data
|
||||
mov si,cs:req_off
|
||||
push cs
|
||||
pop es ;point es to dest buf
|
||||
cld ;Increment on movsb
|
||||
rep movsb ;do the move (ds:si -> es:di for cx)
|
||||
|
||||
; copy done, update cur_count, req_off, req_num
|
||||
mov ax,cs:cur_count
|
||||
add ax,cs:req_dec
|
||||
mov cs:cur_count,ax
|
||||
|
||||
mov ax,cs:req_num
|
||||
sub ax,cs:req_dec
|
||||
mov cs:req_num,ax
|
||||
|
||||
mov ax,cs:req_off
|
||||
add ax,cs:req_dec
|
||||
mov cs:req_off,ax
|
||||
|
||||
;if buf full, write it and check for more
|
||||
mov ax,cs:cur_count
|
||||
cmp ax,cs:cur_buf_sz
|
||||
jb write_e
|
||||
call flush ;write the track
|
||||
cmp ax,1
|
||||
jz write_err
|
||||
jmp write_s ;check for more source data
|
||||
|
||||
write_e: xor ax,ax ;Everything O.K.
|
||||
ret ;Return to caller
|
||||
|
||||
write_err:
|
||||
mov ax,0ah ;send write error
|
||||
ret
|
||||
|
||||
write endp
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; flush a track to diskette, with optional formatting
|
||||
|
||||
flush proc near
|
||||
|
||||
mov cs:tries,0 ;reset error count
|
||||
flush_s: mov ah,cs:do_format ;do we want to format track first?
|
||||
cmp ah,1
|
||||
jnz flush_w
|
||||
|
||||
; format the track first
|
||||
; first set the media descriptor table (ddtp)
|
||||
mov ah, 18h ;set media function
|
||||
mov ch, cs:num_cyl
|
||||
dec ch ;need max cyl number (79)
|
||||
mov cl, cs:cur_num_sec
|
||||
mov dl, cs:cur_drive
|
||||
int 13h ;do set media
|
||||
jc ferror
|
||||
mov ax,0
|
||||
mov ds,ax
|
||||
mov bx,1eh*4 ;bios ptr to ddtp
|
||||
mov ds:[bx],di
|
||||
mov ds:[bx+2],es
|
||||
|
||||
; set up fmt buffer
|
||||
mov ch,1 ;sec number (1..18)
|
||||
mov bx, offset cs:fmt
|
||||
f_fmt: mov ah,cs:cur_cyl
|
||||
mov cs:[bx],ah ;cylinder
|
||||
inc bx
|
||||
mov ah,cs:cur_head
|
||||
mov cs:[bx],ah ;head
|
||||
inc bx
|
||||
mov cs:[bx],ch ;sector
|
||||
inc bx
|
||||
mov ah,2
|
||||
mov cs:[bx],ah ;sector size 2 (512 bytes)
|
||||
inc bx
|
||||
inc ch
|
||||
mov ah,ch
|
||||
cmp ah,cs:cur_num_sec
|
||||
jna f_fmt
|
||||
|
||||
;set up for format call
|
||||
push cs
|
||||
pop es
|
||||
mov bx, offset cs:fmt ;es:bx -> format buffer
|
||||
mov dh,cs:cur_head ;head
|
||||
mov dl,cs:cur_drive ;drive
|
||||
mov ch,cs:cur_cyl ;cylinder
|
||||
mov al,cs:cur_num_sec ;num sectors
|
||||
mov ah,5 ;format command
|
||||
int 13h ;do the format
|
||||
jc ferror
|
||||
|
||||
flush_w: ;write the track
|
||||
mov ah,3 ;write command
|
||||
mov al,cs:cur_num_sec
|
||||
mov ch,cs:cur_cyl
|
||||
mov cl,1 ;start sector
|
||||
mov dh,cs:cur_head
|
||||
mov dl,cs:cur_drive
|
||||
push cs
|
||||
pop es
|
||||
mov bx, cs:buf_start
|
||||
int 13h ;bios write track
|
||||
jnc flush_c
|
||||
|
||||
ferror: ;got error
|
||||
mov ah,cs:tries
|
||||
inc ah
|
||||
cmp ah,3
|
||||
jz flush_f ;3 errors, give up
|
||||
mov cs:tries,ah
|
||||
mov ah,0 ;reset drive
|
||||
mov dl,cs:cur_drive
|
||||
int 13h
|
||||
jmp flush_s ;try again
|
||||
|
||||
flush_c: ;write complete, update pointers
|
||||
xor ax,ax
|
||||
mov cs:cur_count,ax ;zero cur_count
|
||||
mov ah,cs:cur_head
|
||||
xor ah,1 ;bump head
|
||||
mov cs:cur_head,ah
|
||||
cmp ah,1 ;head was 0, so don't bump cyl
|
||||
jz flush_e
|
||||
mov ah,cs:cur_cyl ;head was 1 so bump cyl
|
||||
inc ah
|
||||
cmp ah,80
|
||||
jb flush_d
|
||||
xor ax,ax ;end of disk, zero cyl
|
||||
flush_d: mov cs:cur_cyl,ah
|
||||
|
||||
flush_e:
|
||||
xor ax,ax ;Everything O.K.
|
||||
ret ;Return to caller
|
||||
|
||||
flush_f: mov ax,1 ;return error to write function
|
||||
ret
|
||||
|
||||
flush endp
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; driver open function
|
||||
|
||||
open proc near
|
||||
mov cs:opened_flag,1
|
||||
mov ax,cs:cur_count
|
||||
cmp ax,0
|
||||
jz open_a
|
||||
call flush
|
||||
open_a:
|
||||
call reset
|
||||
xor ax,ax
|
||||
ret
|
||||
open endp
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; driver close function
|
||||
|
||||
close proc near
|
||||
mov cs:opened_flag,0
|
||||
mov ax,cs:cur_count
|
||||
cmp ax,0
|
||||
jz close_a
|
||||
call flush
|
||||
close_a:
|
||||
call reset
|
||||
xor ax,ax
|
||||
ret
|
||||
close endp
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; ioctl write driver function
|
||||
|
||||
ioc_wr proc near
|
||||
lds si, es:[di+b_adr] ;get ioc msg in ds:[si]
|
||||
mov ah,ds:[si] ;get first data char
|
||||
cmp ah,'f' ;is 'f'ormat?
|
||||
jnz ioc_wr_a
|
||||
mov cs:do_format,1
|
||||
jmp ioc_wr_e
|
||||
ioc_wr_a:
|
||||
cmp ah,'n' ;is 'n'o format ?
|
||||
jnz ioc_wr_b
|
||||
mov cs:do_format,0
|
||||
jmp ioc_wr_e
|
||||
ioc_wr_b:
|
||||
cmp ah,'r'
|
||||
jnz ioc_wr_e
|
||||
mov ax,cs:cur_count
|
||||
cmp ax,0
|
||||
jz ioc_wr_c
|
||||
call flush
|
||||
ioc_wr_c:
|
||||
call reset
|
||||
ioc_wr_e:
|
||||
xor ax,ax
|
||||
ret
|
||||
ioc_wr endp
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; reset current write parameters
|
||||
|
||||
reset proc near
|
||||
|
||||
mov cs:cur_count,0
|
||||
mov cs:cur_drive,0
|
||||
mov cs:cur_cyl,0
|
||||
mov cs:cur_head,0
|
||||
|
||||
ret
|
||||
reset endp
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; int 21 handler to make all our opens in binary mode
|
||||
|
||||
orig_int_21 dd ? ;Original INT 21 Vector
|
||||
opened_flag db 0
|
||||
|
||||
our_int_21 proc far
|
||||
pushf ;Save entry flags
|
||||
cmp ah,3Dh ;Is it an open request?
|
||||
jnz not_open_req
|
||||
popf ;Restore entry flags
|
||||
|
||||
sti ;Allow interrupts
|
||||
pushf ;After the iret
|
||||
cli ;Shut interrupts off
|
||||
call cs:orig_int_21 ;While we Pass the request on
|
||||
|
||||
pushf
|
||||
cli
|
||||
cmp cs:opened_flag,0 ;Was it an open for us?
|
||||
jz not_our_open
|
||||
mov cs:opened_flag,0 ;Clear for next time
|
||||
|
||||
push ax
|
||||
mov bx,ax ;Save the Handle
|
||||
mov ax,4400h ;Get Device Information
|
||||
pushf
|
||||
call cs:orig_int_21
|
||||
mov dh,0 ;Setup
|
||||
or dl,20h ;for RAW Mode
|
||||
mov ax,4401h ;Set Device Information
|
||||
pushf
|
||||
call cs:orig_int_21
|
||||
pop ax
|
||||
|
||||
not_our_open: popf ;The Original Flags to return
|
||||
|
||||
ret 2 ;Return and discard flags
|
||||
|
||||
not_open_req: popf ;Pop the saved flags
|
||||
jmp cs:orig_int_21 ;Continue with original code
|
||||
our_int_21 endp
|
||||
|
||||
|
||||
;======================================================================
|
||||
; driver initialization section
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; init - if loaded by config.sys
|
||||
|
||||
init proc near
|
||||
|
||||
;check if this is second call
|
||||
mov ah,cs:init_done
|
||||
cmp ah,0
|
||||
jnz init_e
|
||||
|
||||
;on entry, es:di -> request header
|
||||
lds si, es:[di+18] ;get ds:si -> command line after '='
|
||||
mov al,0 ;counter to limit search
|
||||
|
||||
init_a: mov ah,ds:[si] ;look for first switch character
|
||||
cmp ah, ' '
|
||||
jz init_b ;found a space?
|
||||
cmp ah, 0 ;found a null?
|
||||
jmp init_f ;if so, nothing to do
|
||||
inc si
|
||||
inc al
|
||||
cmp al,128 ;we will look for 128 chars in tail
|
||||
jnz init_a ;keep on looking
|
||||
jmp init_f ;give up
|
||||
|
||||
init_b: inc si ;got a space
|
||||
mov ah,ds:[si] ;this is first arg
|
||||
cmp ah,'N' ;dos makes the line all uppercase
|
||||
jnz init_f ;if not 'N' then nothing to do
|
||||
mov cs:do_format,0 ;got 'N', so reset do_format
|
||||
|
||||
init_f:
|
||||
call do_init ;method independent initialization
|
||||
call patch_us_in ;raw open checker
|
||||
|
||||
init_e:
|
||||
mov cs:init_done,1
|
||||
;set end address of driver -- keep init, as it is called twice
|
||||
les di,dword ptr cs:db_ptr ;req header address to ES:DI
|
||||
mov ax,cs:buf_end
|
||||
mov es:[di+end_adr],ax
|
||||
mov es:[di+end_adr+2],cs
|
||||
xor ax,ax
|
||||
ret
|
||||
init endp
|
||||
|
||||
;-------------------------------------------------------------------------
|
||||
; init code common to driver or exe loading
|
||||
|
||||
do_init proc near
|
||||
;get drive params
|
||||
;default is drive a: 1.44, drive b: 1.2M
|
||||
mov ah,8 ;get drive type
|
||||
mov dl,0 ;drive a:
|
||||
int 13h
|
||||
cmp bl,4 ;is drive 0 type 4 (1.44M)?
|
||||
jz do_init_a
|
||||
mov cs:num_sec_a,NUM_SEC_2 ;not type 4 - then assume type 2
|
||||
mov cs:buf_sz_a,BUF_SZ_2
|
||||
do_init_a:
|
||||
mov ah,8 ;get drive type
|
||||
mov dl,1 ;drive b:
|
||||
int 13h
|
||||
cmp bl,2 ;is drive b: type 2 (1.44M)?
|
||||
jz do_init_b
|
||||
mov cs:num_sec_a,NUM_SEC_4 ;not type 2 - then assume type 4
|
||||
mov cs:buf_sz_a,BUF_SZ_4
|
||||
do_init_b:
|
||||
;setup track buf start and end offsets
|
||||
mov ax, offset cs:patch_end
|
||||
mov cs:buf_start, ax
|
||||
add ax,BUF_SZ_4
|
||||
mov cs:buf_end,ax
|
||||
|
||||
;check if it crosses 64K DMA boundary
|
||||
mov cl,4
|
||||
push cs
|
||||
pop dx
|
||||
mov ax, cs:buf_start ;compute buf_start's top nibble
|
||||
shr ax,cl
|
||||
add ax,dx
|
||||
and ax,0f000h
|
||||
mov bx,ax ;save buf_start's in bx
|
||||
mov ax, cs:buf_end ;compute buf_end's top nibble
|
||||
shr ax,cl
|
||||
add ax,dx
|
||||
and ax,0f000h
|
||||
cmp ax,bx ;compare them
|
||||
jz do_init_e ;same, so buf OK
|
||||
mov ax,cs:buf_end
|
||||
mov cs:buf_start,ax ;first buf bad, so move to its end
|
||||
add ax,BUF_SZ_4
|
||||
mov cs:buf_end,ax
|
||||
do_init_e:
|
||||
;add psp and good luck
|
||||
mov ax,cs:buf_end
|
||||
add ax,200h
|
||||
mov cs:buf_end,ax
|
||||
ret
|
||||
|
||||
do_init endp
|
||||
|
||||
;---------------------------------------------------------------------
|
||||
; initialization code to patch in our int 21 handler
|
||||
|
||||
vect_int_21 equ word ptr 4 * 21h
|
||||
|
||||
patch_us_in proc near
|
||||
cli
|
||||
mov ax,0 ;Patch Ourselves into
|
||||
mov es,ax ;the INT 21 Vector
|
||||
mov ax,es:[vect_int_21] ;Offset
|
||||
mov word ptr cs:orig_int_21,ax
|
||||
mov ax, offset cs:our_int_21
|
||||
mov es:[vect_int_21],ax
|
||||
mov ax,es:[vect_int_21+2] ;Segment
|
||||
mov word ptr cs:orig_int_21+2,ax
|
||||
mov ax,cs
|
||||
mov es:[vect_int_21+2],ax
|
||||
sti
|
||||
ret
|
||||
patch_end:
|
||||
patch_us_in endp
|
||||
|
||||
;======================================================================
|
||||
; exe section: load driver or send ioctl
|
||||
|
||||
; Equates
|
||||
|
||||
DOS_GET_VER equ 30h
|
||||
DOS_RELEASE_MEM equ 49h
|
||||
DOS_TSR_FUNC equ 31h
|
||||
DOS_LIST_LISTS equ 52h ;undocumented call to get "list of lists"
|
||||
|
||||
; structs:
|
||||
;
|
||||
doub_word struc
|
||||
d_offset dw ?
|
||||
d_segment dw ?
|
||||
doub_word ends
|
||||
|
||||
list_lists30 struc ;list of lists info (DOS 3.0)
|
||||
dpb_ptr30 dd ? ;ptr 1st DOS DPB
|
||||
file_tab30 dd ? ;ptr DOS file tables
|
||||
clock_ptr30 dd ? ;ptr to CLOCK$ device
|
||||
con_ptr30 dd ? ;ptr to CON device
|
||||
num_blk30 db ? ;number block devices
|
||||
max_byte30 dw ? ;max bytes/block
|
||||
dsk_buf30 dd ? ;ptr 1st disk buffer
|
||||
cds_ptr30 dd ? ;ptr to current disk struc
|
||||
last_drv30 db ? ;LASTDRIVE value
|
||||
strg_wrk30 dd ? ;STRING workspace area
|
||||
srg_size30 dw ? ;size of STRING area
|
||||
fcb_tab30 dd ? ;ptr to FCB table
|
||||
fcb_y_30 dw ? ;y in FCBs=x,y
|
||||
nul_dev30 db 18 dup(?) ;NUL device header
|
||||
list_lists30 ends
|
||||
|
||||
list_lists31 struc ;list of lists info (DOS 3.1)
|
||||
dpb_ptr31 dd ? ;ptr 1st DOS DPB
|
||||
file_tab31 dd ? ;ptr DOS file tables
|
||||
clock_ptr31 dd ? ;ptr to CLOCK$ device
|
||||
con_ptr31 dd ? ;ptr to CON device
|
||||
max_byte31 dw ? ;max bytes/block
|
||||
dsk_buf31 dd ? ;ptr 1st disk buffer
|
||||
cds_ptr31 dd ? ;ptr to current disk struc
|
||||
fcb_tab31 dd ? ;ptr to FCB table
|
||||
fcb_y_31 dw ? ;y in FCBs=x,y
|
||||
num_blk31 db ? ;number block devices
|
||||
last_drv31 db ? ;LASTDRIVE value
|
||||
nul_dev31 db 18 dup(?) ;NUL device header
|
||||
num_join31 db ? ;number of JOINed drives
|
||||
list_lists31 ends
|
||||
|
||||
dev_header struc
|
||||
dev_chain dd ?
|
||||
dev_attrib dw ?
|
||||
dev_stratr dw ?
|
||||
dev_intr dw ?
|
||||
dev_num_units db ? ;first byte of char name
|
||||
dev_char_name db 7 dup(?)
|
||||
dev_header ends
|
||||
|
||||
ver_spec_off struc ;version specific offsets
|
||||
vcds_ptr dw ? ;offset of CDS ptr
|
||||
vdpb_ptr dw ? ;offset of DPB ptr
|
||||
vnul_dev_ptr dw ? ;offset of NUL device header
|
||||
vlast_drive dw ? ;offset of LASTDRIVE
|
||||
ver_spec_off ends
|
||||
|
||||
; data:
|
||||
;
|
||||
dos_ver dw 0
|
||||
nul_dev_ptr dd ? ;pointer to NUL device
|
||||
|
||||
dos30_ver_off ver_spec_off <cds_ptr30,dpb_ptr30,nul_dev30,last_drv30>
|
||||
dos31_ver_off ver_spec_off <cds_ptr31,dpb_ptr31,nul_dev31,last_drv31>
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; entry point if run as exe
|
||||
|
||||
exe_start proc near
|
||||
call do_args ;get first option char
|
||||
call do_ioc ;exits if drv already loaded
|
||||
call do_init ;init driver
|
||||
call patch_us_in
|
||||
call get_list_ptr ;find nul dev header
|
||||
call add_to_chain ;add rawfda and rawfdb to chain
|
||||
call go_tsr ;leave driver resident
|
||||
exe_start endp
|
||||
|
||||
;--------------------------------------------------------------
|
||||
;set do_format and ioc_msg based on args
|
||||
|
||||
do_args proc near
|
||||
;the exe program is just starting, so ds is still PSP
|
||||
|
||||
;set defaults
|
||||
mov cs:do_format,1 ;default is format
|
||||
mov cs:ioc_msg, byte ptr 'r'
|
||||
|
||||
mov si,82h
|
||||
mov ah,ds:[si]
|
||||
cmp ah,'n'
|
||||
jnz do_args_a
|
||||
mov cs:ioc_msg, byte ptr 'n'
|
||||
mov cs:do_format,0
|
||||
ret
|
||||
|
||||
do_args_a:
|
||||
cmp ah,'f'
|
||||
jnz do_args_b
|
||||
mov cs:ioc_msg, byte ptr 'f'
|
||||
mov cs:do_format,1
|
||||
ret
|
||||
do_args_b:
|
||||
cmp ah,'r'
|
||||
jnz do_args_e
|
||||
mov cs:ioc_msg, byte ptr 'r'
|
||||
|
||||
do_args_e:
|
||||
ret
|
||||
do_args endp
|
||||
|
||||
;--------------------------------------------------------------
|
||||
; see if driver is loaded, and if so, send command switch via ioctl
|
||||
|
||||
drv_name db 'RAWFDA',0h
|
||||
ioc_msg db 'n'
|
||||
|
||||
do_ioc proc near
|
||||
|
||||
;try to open rawfda using file handle call
|
||||
push cs
|
||||
pop ds
|
||||
mov al,2 ;read/write access
|
||||
mov ah,3dh ;open file handle
|
||||
lea dx,drv_name ;filename
|
||||
int 21h ;do it
|
||||
jc do_ioc_e ;failed, ret to load driver
|
||||
|
||||
;do ioctl write ;succeeded, so just send ioctl
|
||||
push cs
|
||||
pop ds
|
||||
mov bx,ax ;handle ->bx
|
||||
mov ah,44h ;ioctl
|
||||
mov al,3 ;write
|
||||
mov cx,1 ;length of write
|
||||
lea dx,ioc_msg ;msg buf
|
||||
int 21h ;doit
|
||||
|
||||
;simply exit now
|
||||
mov ax,4c00h
|
||||
int 21h
|
||||
|
||||
do_ioc_e:
|
||||
ret
|
||||
do_ioc endp
|
||||
|
||||
;--------------------------------------------------------------
|
||||
;get_list_ptr - Use Undocumented DOS function 52h to
|
||||
; retrieve pointer to NUL driver header.
|
||||
|
||||
get_list_ptr proc near
|
||||
mov ax,3000h
|
||||
int 21h ; get dos version
|
||||
mov cs:dos_ver,ax
|
||||
mov ah, DOS_LIST_LISTS
|
||||
int 21h ;get list of lists
|
||||
mov di, offset cs:dos31_ver_off ;default to 3.1 >
|
||||
cmp byte ptr cs:dos_ver, 4 ;maj ver 4 >?
|
||||
jae get_list100
|
||||
cmp dos_ver, 300h ;is it 3.0?
|
||||
jne get_list100
|
||||
mov di, offset cs:dos30_ver_off ;offsets for 3.0
|
||||
get_list100:
|
||||
mov si, cs:[di].vnul_dev_ptr ;offset to NUL ptr
|
||||
mov ax, es ;get seg NUL dev
|
||||
mov cs:nul_dev_ptr.d_segment, ax
|
||||
add si, bx
|
||||
mov cs:nul_dev_ptr.d_offset, si ;offset of NUL dev
|
||||
|
||||
get_list999:
|
||||
ret
|
||||
get_list_ptr endp
|
||||
|
||||
;--------------------------------------------------------------
|
||||
;add_to_chain - Add driver to driver chain.
|
||||
;
|
||||
|
||||
add_to_chain proc near
|
||||
|
||||
lds si, cs:nul_dev_ptr ;point to NUL header
|
||||
mov ax, [si].dev_chain.d_offset ;ptr to next drvr
|
||||
mov dx, [si].dev_chain.d_segment
|
||||
|
||||
cli
|
||||
; point NUL -> hdr_a (es:bx)
|
||||
mov bx, offset cs:hdr_a
|
||||
mov [si].dev_chain.d_offset, bx ;put ours in list
|
||||
push cs
|
||||
pop es
|
||||
mov [si].dev_chain.d_segment, es
|
||||
|
||||
; point hdr_a -> hdr_b (offset is already set)
|
||||
mov es:[bx+2],es
|
||||
|
||||
; point hdr_b -> orig next dev (dx:ax)
|
||||
mov bx, offset cs:hdr_b
|
||||
mov es:[bx].dev_chain.d_offset, ax ;link to
|
||||
mov es:[bx].dev_chain.d_segment, dx ;old 1st drvr
|
||||
sti
|
||||
ret
|
||||
add_to_chain endp
|
||||
|
||||
;--------------------------------------------------------------
|
||||
;go_tsr - Free our environment and then terminate and stay resident
|
||||
|
||||
go_tsr proc near
|
||||
|
||||
mov bx, cs:buf_end
|
||||
mov cl,4
|
||||
shr bx,cl
|
||||
mov ah, DOS_RELEASE_MEM
|
||||
push bx
|
||||
int 21h
|
||||
|
||||
pop dx
|
||||
mov ax, (DOS_TSR_FUNC SHL 8) ;exit code 0
|
||||
int 21h ;Go TSR
|
||||
tail: ret
|
||||
|
||||
go_tsr endp
|
||||
|
||||
;======================================================================
|
||||
|
||||
code ends
|
||||
end exe_start
|
||||
Reference in New Issue
Block a user