home *** CD-ROM | disk | FTP | other *** search
-
- NAME Device_Driver_Installer
- TITLE Idrv.asm
- ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;
- ; 18-11-1991 ;
- ; Idrv.asm (v1.06) ;
- ; compiled with Turbo Assembler v1.0 ;
- ; by Janusz Wojcik ;
- ; Lublin,Poland. ;
- ;..............................................................................;
-
-
- ASSUME DS:st_seg, SS:st_seg ,CS:st_seg ,ES:st_seg
- st_seg SEGMENT
- ORG 100h
-
- start:
- mov ax,es
- dec ax
- mov es,ax ;ES = ES - 1
- mov ax,word ptr es:3 ;get size of memory block from MCB
- push ax
- mov bx,es
- add ax,bx ;compute address of the end of memory block
- mov bx,LEN + 15 ;compute size of the program ...
- mov cl,4
- shr bx,cl ; ... in paragraphs
- sub ax,bx ;calculate new address of program's beginning
-
- mov jmp_seg,ax ;save it
- mov es,ax
- ;.......................................................
- pop ax
- mov dx,10h ;add PSP size
- add dx,bx
- sub ax,dx
- cmp ax,1000h ;some drivers set stack at the ...
- ; ... end of the segment !!!
- ja move_code ;jump if more than 64KB left
- lea dx,too_small
- mov ah,9
- int 21h
-
- mov ah,4ch ;EXIT
- mov al,1 ;Set return code
- int 21h
- ;.......................................................
- move_code:
- mov cx,LEN
- mov di,0
- mov si,offset pr_end
- cld
- rep movsb ;move program into upper memory
-
- jmp dword ptr jmp_offs ;and go there
-
- too_small db 'IDrv: Too small memory!',cr,lf,lf,'$'
-
- jmp_offs dw 0
- jmp_seg dw 0
-
- ALIGN 16
- pr_end equ $
-
- st_seg ends
- ;*******************************************************************************
-
- ASSUME DS:code, SS:code ,CS:code ,ES:code
- code SEGMENT Byte Public 'code'
-
- new_seg equ $
- mov ax,cs
- cli
- mov ss,ax ;Set own stack
- mov sp,offset EOS
- sti
-
- mov ax,ds
- push cs
- pop ds ;DS = CS
- mov our_seg,ax
-
- jmp starter ; jump over data
- own_stack db 157 dup(0)
- EOS equ $ ; End Of Stack
-
-
- ;...............................................................................
-
- device_header struc
- next_offs dw ?
- next_seg dw ?
- dev_attr dw ?
- dev_strategy dw ?
- dev_interrupt dw ?
- name_unit db 8 dup(?)
- device_header ends
-
- ;Idrv Control Block
- icb struc
- signature db 7 dup(?)
- xms_marker db 3 dup(?)
- prv_xms_offs dw ?
- prv_xms_seg dw ?
- xms_handle dw ?
- icb ends
- .errnz 16 - SIZE icb
- ;...............................................................................
-
- lf equ 0ah ; line feed
- cr equ 0dh ; carriage return
-
- ZERO equ 0
- INIT equ 0
- TAB equ 9
-
- DIB_SIZE equ 21h
- FIRST_DIB equ 26h
- FIRST_DA equ 3ch
- NUM_OF_DRV equ 46h
- TOTAL_NUM equ 47h
- MAX_SECTOR equ 36h
- JMP_SHORT equ 3ebh
- JMP_FAR equ 0eah
-
- ;...............................................................................
- ; the program body
- ;..............................................................................
- ldrv:
- call load_drv
- jnc idev
- jmp exit
-
- idev:
- mov es,dos_seg
- mov al,byte ptr es:NUM_OF_DRV ;Get real number of drives
- mov drive_num,al ;Set unit number in Req. Header
- call init_dev ;INIT device
- jnc modify_mem
- call restore_xms ;restore previous state of original XMS handler
- lea dx,err3
- jmp exit
- modify_mem:
- call restore_xms ;restore previous state of original XMS handler
- test flags,UMB_USED ;Driver in other mem. block ?
- jz create_cb ;No,skip
- mov bx,ending_offset
- add bx,15
- rcr bx,1
- mov cl,3
- shr bx,cl
- add bx,ending_segment
- mov ax,dev_seg
- dec ax ;take into account ICB size!
- sub bx,ax ;BX - size of mem. block in paragraphs
- mov es,ax ;ES - seg. of the block
- mov ah,4ah ;Modify alloc. mem. block
- int 21h
- jnc create_cb
- lea dx,err7
- jmp exit_err
- create_cb:
- mov ax,dev_seg
- mov es,ax
- mov bx,drv_beg
- call create_icb ;create Idrv Control Block
- mov ax,es:dev_attr[bx]
- test ah,80h ;Character device ?
- jnz ldev ;Yes,jump to link device headers
- cmp units,ZERO ;Error during INIT ?
- jnz check_CDS ;No
- lea dx,err3
- jmp exit ;Yes,jump to quit
- check_CDS:
- call check_DA
- jc exit_err
- DIB_creation:
- call seek_last ;Seek the last DIB
- mov lastDIB_offs,bx
- mov lastDIB_seg,es
-
- test flags,UMB_USED ;driver in other mem.block ?
- jz DIB_after_drv ;No,jump
- mov ax,our_seg
- add ax,10h ;add PSP size
- jmp set_DIB_addr
-
- DIB_after_drv:
- mov ax,ending_offset
- add ax,15
- mov cl,4
- shr ax,cl
- add ax,ending_segment
- set_DIB_addr:
- mov DIB_seg,ax
- mov DIB_offs,ZERO
-
- mov cl,units ;CX = number of units
- xor ch,ch
- mov dl,es:[bx] ;DL = last drive#
- mov dh,0ffh
- DIB_continue:
- inc dl ;Set drive#
- inc dh ;Set unit#
- call create_DIB ;Create Disk Info Block
- jnc DA_creation
- call restore ;Restore previous state of DIB & DA chains
- jmp exit_err
- DA_creation:
- call create_DA ;Create Disk Area
- les bx,dword ptr DIB_offs
- add DIB_offs,DIB_SIZE ;Set new DIB address
- loop DIB_continue
-
- ldev: call link_dev ;Link device headers
- jmp exit_OK
- exit_err:
- call free_xmem
- call print_msg
-
- exit_OK:
- mov ax,our_seg
- mov es,ax
- mov es,es:2ch
- mov ah,49h ; Free allocated memory (environment)
- int 21h
-
- test flags,UMB_USED ; Driver in UMB ?
- jz drv_not_high ; No,jump
- mov dx,100h ; size of PSP
- add dx,ad_mem
- add dx,15
- rcr dx,1
- mov cl,3
- shr dx,cl
- jmp term_resident
-
- drv_not_high:
- mov dx,ending_offset ;Compute address of ...
- add dx,ad_mem
- add dx,15
- rcr dx,1
- mov cl,3
- shr dx,cl
-
- add dx,ending_segment
- inc dx ; (add one para)
- mov ax,our_seg
- sub dx,ax ; ... program end
- term_resident:
- xor al,al ; set 0 for return code
- mov ah,31h ;Terminate and remain resident
- int 21h
-
- exit:
- call print_msg
- exit_no_print:
- mov ah,4ch ;EXIT
- mov al,1 ;Set return code
- int 21h
- ;..............................................................................
- ; create_icb:
- ; creates Idrv Control Block before Device Header
- ; Input:
- ; ES:BX - Device Header address
- ;..............................................................................
- create_icb proc near
-
- push es
- mov ax,es
- dec ax
- mov es,ax
- mov si,offset sign
- mov cx,SIG_LEN
- mov di,bx
- cld
- rep movsb ;place signature
- mov ax,handle
- mov word ptr es:xms_marker[bx],ax ;the word will be ...
- ; ... 0 if handle is 0
- cmp ax,ZERO
- je xms_not_used
- mov word ptr es:xms_handle[bx],ax
- mov byte ptr es:xms_marker[bx],'X' ;signal that XMS was used
- mov word ptr es:xms_marker[bx + 1],'SM'
- mov ax,prv_offs
- mov word ptr es:prv_xms_offs[bx],ax
- mov ax,prv_seg
- mov word ptr es:prv_xms_seg[bx],ax
- xms_not_used:
- pop es
- ret
- create_icb endp
-
- page;..........................................................................
- ; link_dev: .......
- ; links Device Header of the driver with the chain of .......
- ; Device Headers of the rest drivers ....... .......
- ;..............................................................................
-
-
- link_dev:
- mov es,dos_seg
- mov si,48h
- push es
- les si,dword ptr es:[si] ;Address of next dev. header
- mov bx,drv_beg
- mov ax,dev_seg
- push ds
- mov ds,ax
- mov next_offs[bx],si
- mov next_seg[bx],es
- mov bx,dev_attr[bx] ;get dev.attribute for later
- pop ds
-
- pop es
- cli
- mov es:48h,word ptr ZERO
- mov ax,dev_seg
- mov es:4ah,ax
- sti
-
- test bl,1 ;Is it Stdin device ?
- jz test_clk ;No,jump
- mov es:32h,word ptr ZERO ;Change pointer to ...
- mov es:34h,ax ; ... Stdin
- les bx,es:02ah ;Get address of DOS file table
- add bx,dos_dep ;change entry length of OFT if necessary
- mov es:[bx + 042h],word ptr ZERO ;Change address of dev.header ...
- mov es:[bx + 044h],ax ; ... in Open Files Table
- jmp quit_link
-
- test_clk: test bl,8 ;Is it clock device ?
- jz quit_link ;No,jump
- mov es:2eh,word ptr ZERO
- mov es:30h,ax
-
- quit_link:
- ret
-
- ;..............................................................................
- ; load_drv: .......
- ; loads device driver code into memory .......
- ;..............................................................................
- load_drv:
- call get_file_len
- jc quit_load
- call alloc_umb
- mov ax,dev_seg
- xor dx,dx
- push ds
- mov ds,ax ;DS:DX - buffer address
- mov ah,3fh ;READ
- int 21h
- pop ds
- lea dx,err12
- jc quit_load
-
- mov ah,3eh ;CLOSE
- int 21h
- quit_load:
- ret
- ;...............................................................................
- ; get_file_len:
- ; checks file length.
- ; OUTPUT:
- ; BX - file handle
- ; CX - file length
- ;...............................................................................
- get_file_len proc near
- mov ah,3dh ;OPEN
- mov dx,offset fname
- mov al,0
- int 21h
- lea dx,err10
- jc quit_get
-
- mov bx,ax ;save file handle
- mov ah,42h ;LSEEK ...
- mov al,2 ; ... to the end of file
- mov cx,ZERO
- mov dx,ZERO
- int 21h
- jnc get_cont1
- lea dx,err11
- jmp quit_get
- get_cont1:
- or dx,dx ;DX:AX - file length
- jz get_cont2
- stc
- lea dx,err13
- jmp quit_get
- get_cont2:
- push ax
- mov ah,42h ;LSEEK ...
- mov al,0 ; ... to the beginning
- xor cx,cx
- xor dx,dx
- int 21h
- lea dx,err11
- pop cx
- quit_get:
- ret
- get_file_len endp
- ;...............................................................................
- ; alloc_umb:
- ; allocates Upper Memory Block if necessary
- ; INPUT:
- ; CX - file size in bytes
- ;...............................................................................
- alloc_umb:
- test flags,DOS_V5 ;DOS v5.xx and load high ?
- jz alloc_end ;No,jump
- test flags,LOAD_HIGH
- jz alloc_end ;No,jump
- push bx
- push cx ;save size of the file
-
- mov ax,5800h ;get memory allocation flags
- int 21h
- mov mem_flag,al ;save flags
-
- mov ax,5802h ;get link status
- int 21h
- mov link_stat,al
-
- mov ax,5801h ;search upper mem. for first fit
- mov bx,80h
- int 21h
-
- mov ax,5803h ;set link status
- mov bx,1
- int 21h
- jc restore_alloc_flag
-
- mov bx,cx ;BX = file size
- add bx,0fh
- rcr bx,1
- mov cx,3
- shr bx,cl ;BX = size of mem. in paragraphs
- inc bx ;add one paragraph for ICB
- mov ah,48h ;allocate memory
- int 21h
- jc restore_alloc_flag
- inc ax ;driver will be placed after ICB
- mov dev_seg,ax
- or flags,UMB_USED ;driver is in other mem. block
- restore_alloc_flag:
- xor bh,bh
- mov bl,mem_flag
- mov ax,5801h ;restore allocation flags
- int 21h
-
- mov ax,5803h ;restore link status
- xor bh,bh
- mov bl,link_stat
- int 21h
-
- pop cx
- pop bx
- alloc_end:
- ret
-
-
- ;...............................................................................
- ; init_dev:
- ; calls Strategy and Interrupt Routines of the device driver
- ;...............................................................................
- init_dev:
- mov si,drv_beg
- mov ax,dev_seg
- mov es,ax
- mov ax,es:dev_strategy[si] ;get addr. of strategy routine
- mov dev_offs,ax
- mov ax,es:dev_interrupt[si] ;get addr. of interrupt routine
- push ax ;save it for later
-
- push cs
- pop es ;ES = CS
- mov bx,offset Request_Header ;ES:BX - Request Header
-
- call dword ptr dev_offs ;Call dev. strategy routine
-
- pop ax
- mov dev_offs,ax
-
- call dword ptr dev_offs ;Call dev. interrupt routine
- mov ax,ending_offset
- or ax,ax
- jnz quit_init
- mov ax,ending_segment
- cmp ax,dev_seg
- ja quit_init
- stc
- ret
- quit_init:
- clc
- ret
- ;...............................................................................
- ; print_msg:
- ; displays the message.
- ; INPUT:
- ; DS:DX - pointer to the character string
- ;...............................................................................
- print_msg:
- mov ah,9
- int 21h
- ret
- ;...............................................................................
- ; seek_last:
- ; seeks the last Disk Info Block
- ; OUTPUT:
- ; ES:BX - last DIB
- ;...............................................................................
- seek_last proc near
-
- mov es,dos_seg
- les bx,es:FIRST_DIB ;Get address of first DIB
- mov si,dos_dep3
- next_DIB: cmp word ptr es:[si + bx + 18h],0ffffh ;The last DIB ?
- jz seek_end ;Yes,jump
- les bx,dword ptr es:[si + bx + 18h] ;Get addr. of next DIB
- jmp next_DIB
- seek_end: ret
-
- seek_last endp
- ;................................................................................
- ; create_DIB:
- ; creates Disk Info Block for the drive
- ; INPUT:
- ; ES:BX - last DIB
- ; DL - drive#
- ; DH - unit#
- ;
- ; OUTPUT:
- ; ES:BX - address of created DIB
- ;................................................................................
- create_DIB proc near
-
-
- push ds
-
- mov ax,DIB_offs
- mov si,dos_dep3
- mov word ptr es:[si + bx + 18h],ax ;Chain ...
- mov ax,DIB_seg ; ...
- mov word ptr es:[si + bx + 1ah],ax ; ... DIBs
-
- les bp,dword ptr DIB_offs ;ES:BP - next DIB address
- mov word ptr es:[bp],dx ;Set drive and unit #
- mov word ptr es:[si + bp + 18h],0ffffh ;Mark it as the last DIB
- mov byte ptr es:[si + bp + 17h],0ffh ;Init access flag
- mov word ptr es:[si + bp + 12h],ZERO ;Set address of ...
- mov ax,dev_seg
- mov word ptr es:[si + bp + 14h],ax ; ... device header
-
- lds si,dword ptr args_offset ;DS:SI = pointer to BPB
- push ax
- mov al,dh
- xor ah,ah
- mul cs:two
- add si,ax
- mov si,[si] ;Get BPB address
- pop ds ;DS = driver segment
- mov ah,53h
- int 21h ;Build DIB
- mov ax,es:[bp + 2] ;Get sector size from DIB
- mov es,cs:dos_seg
- add cs:ad_mem,DIB_SIZE ;Add DIB size
- cmp ax,es:MAX_SECTOR ;Compare it with max. sector size
- jbe create_ok ;If smaller than OK
- ; les bp,dword ptr cs:DIB_offs ;ES:BP - current DIB address
- ; dec byte ptr es:[bp] ;decrement drive number
- lea dx,err5
- stc
- jmp drop_regs
- create_ok: clc
-
- drop_regs:
- pop ds
- ret
-
- create_DIB endp
- ;...............................................................................
- ; create_DA:
- ; creates Drive Area (or else Current Directory Structure) for the drive
- ;...............................................................................
- create_DA proc near
-
- push cx
- push dx
-
- mov es,dos_seg
- inc byte ptr es:NUM_OF_DRV ;Increase real number of drives
- mov al,byte ptr es:NUM_OF_DRV
- call get_DA_addr
- add al,40h ;Convert to ASCI letter
- mov es:[di],al ;Put it into DA
- add di,43h
- mov ax,4000h ;Signal that drive exists
- stosw
- mov ax,DIB_offs
- stosw ;Set DIB offset
- mov ax,DIB_seg
- stosw ;Set DIB segment
- mov ax,0
- stosw
- mov ax,0ffffh
- stosw
- stosw
- mov ax,2
- stosw
- create_end:
- pop dx
- pop cx
-
- ret
-
- create_DA endp
- ;...............................................................................;
- ; get_DA_addr:
- ; calculates address of Drive Area for drive AL
- ; INPUT:
- ; AL - drive number,eg. 1 - A:, 2 - B:, ...
- ;
- ; OUTPUT: ;
- ; ES:DI - address of Drive Area for drive AL ;
- ;...............................................................................;
- get_DA_addr proc near
-
- push ax
- push dx
- dec al
- xor ah,ah
- mov dl,51h ;Set DA ...
- add dl,dos_dep2 ; ... size
- mul dl ;Multiply by DA size
- mov es,dos_seg
- les di,dword ptr es:FIRST_DA ;Get addr. of first DA
- add di,ax ;So now ES:DI points to new DA
- pop dx
- pop ax
- ret
-
- get_DA_addr endp
- ;...............................................................................
- ; check_DA:
- ; checks whether already installed devices are not network or SUBSTed ones
- ;...............................................................................
- check_DA proc near
-
- mov es,dos_seg
- mov al,byte ptr es:NUM_OF_DRV ;Get real number of drives
- xor ch,ch
- mov cl,units
- mov ah,byte ptr es:TOTAL_NUM ;Get total number of drives
- check_next_DA:
- inc al
- cmp al,ah
- lea dx,err4
- ja check_err_end
- call get_DA_addr ;Get address of DA to ES:DI
- cmp word ptr es:[di + 43h],ZERO ;DA not used ?
- jz check_loop ;Yes,jump
- lea dx,err6
- check_err_end:
- stc ;Signal error
- ret
- check_loop:
- loop check_next_DA
- clc
- ret
-
- check_DA endp
- ;................................................................................
- ; restore:
- ; restores previous state of Drive Area
- ;................................................................................
- restore proc near
-
- les bx,dword ptr lastDIB_offs
- mov si,dos_dep3
- mov word ptr es:[si + bx + 18h],0ffffh ;Mark it as the last DIB
- mov al,es:[bx] ;Get last drive nimber
- inc al
- mov es,dos_seg
- mov ah,byte ptr es:NUM_OF_DRV ;Get real number of drives
- mov byte ptr es:NUM_OF_DRV,al ;Restore real number of drives
- cmp_numb:
- cmp ah,al
- jz restore_end
- inc al
- call get_DA_addr ;Get address of DA to ES:DI
- mov word ptr es:[di + 43h],ZERO ;Mark DA as not used
- jmp cmp_numb
- restore_end:
- ret
-
- restore endp
- ;.................................................................................
- two db 2 ;byte = 2h
-
- DOS_V5 equ 1
- UMB_USED equ 2
- LOAD_HIGH equ 4
- OWN_XMS equ 8
-
- flags db 0 ;B0 set if DOS v5.xx
- ;B1 set if UMB used
- ;B2 set if driver is to be load high
- ;B3 set if XMS handler changed
-
- mem_flag db 0 ;memory allocation flag
- link_stat db 0 ;UMB link status
-
- dos_dep dw 0 ;0 - if dos 3.xx, 6 - if dos 4.xx or 5.xx
- dos_dep2 db 0 ;0 - if dos 3.xx, 7 - if dos 4.xx or 5.xx
- dos_dep3 dw 0 ;0 - if dos 3.xx, 1 - if dos 4.xx or 5.xx
-
- dos_seg dw 0 ;IMBDOS segment
- our_seg dw 0 ;our initial segment
- ad_mem dw 0 ;Mem. occupied by DIBs
- drv_beg dw 0 ;Start of driver (must be on para boundry)
- drv_seg dw 0 ;Segment addr. of driver
-
- dev_offs dw 0 ;Pointer to driver ...
- dev_seg dw 0 ; ... strat/interr routine
-
- DIB_offs dw 0 ;Address of ...
- DIB_seg dw 0 ; ... driver's DIB
-
- lastDIB_offs dw 0 ;Address of ...
- lastDIB_seg dw 0 ; ... the last DIB
-
- Request_Header label byte
- header_length db HLEN
- unit_code db ?
- command_code db INIT
- status dw 0
- reserved dq 0
-
- units db ?
- ending_offset dw ?
- ending_segment dw ?
- args_offset dw ?
- args_seg dw ?
- drive_num db ?
- HLEN equ $ - header_length
- error_msg dw 0 ;used by DOS v4.xx
- HLEN2 equ $ - header_length
-
- sign db 'IdrvCB '
- SIG_LEN equ $ - sign
-
- ;...............................................................................
- fname db 128 dup (0)
-
- err3 db 'IDrv: INIT error!',cr,lf,lf,'$'
- err4 db 'IDrv: Too small LASTDRIVE specified!',cr,lf,lf,'$'
- err5 db 'IDrv: Sector size too large!',cr,lf,lf,'$'
- err6 db "IDrv: Can't install device after SUBSTed and network device!",cr,lf,lf,'$'
- err7 db 'IDrv: Memory allocation error!',cr,lf,lf,'$'
- ;...............................................................................
- err10 db 'IDrv: File not found!',cr,lf,lf,'$'
- err11 db 'IDrv: SEEK error!',cr,lf,lf,'$'
- err12 db 'IDrv: READ error!',cr,lf,lf,'$'
- err13 db 'IDrv: File too large!',cr,lf,lf,'$'
- ;...............................................................................
-
-
- starter: lea dx,header
- call print_msg
- mov ah,30h
- int 21h ;Get DOS version number
- lea dx,err_txt
- cmp al,3
- jb pr_txt
- check_ver:
- je get_list ;DOS v3.xx
- cmp al,5 ;ver. above 5 ?
- ja pr_txt ;yes,jump
- jne dos_v4
- or flags,DOS_V5 ;DOS v5.xx
- dos_v4:
- mov dos_dep,6 ;No,change entry length of Open Files Table
- mov dos_dep2,7 ;Change entry length of Drive Area
- mov dos_dep3,1 ;Change entry length of Disk Info Block
- mov header_length,HLEN2 ;Increase header length
- get_list:
- mov ah,52h
- int 21h ;Get vector for int 25H
- mov dos_seg,es
- lea dx,not_PC_Dos
- cmp word ptr es:52h,'UN' ;NUL device ?
- jne pr_txt ;No,jump
- les di,dword ptr es:02ah ;get address of DOS file table
- add di,dos_dep ;change entry length of OFT if necessary
- cmp byte ptr es:[di + 05bh],'C' ;Entry for dev. CON ?
- jne pr_txt
- cmp word ptr es:[di + 05ch],'NO'
- jne pr_txt
-
- mov si,80h
- mov ax,our_seg
- mov es,ax
- mov di,offset fname
- xor cx,cx
- get_char: inc si
- mov al,es:[si]
- cmp al,CR
- jz end_of_name
- cmp al,TAB ;Is it Tab ?
- jz is_any ;Yes,jump
- cmp al,' ' ;Is it space ?
- jnz check_if_first ;No,jump
- is_any:
- or cx,cx ;Any char moved ?
- jz get_char ;No,jump to get next char
- jmp go_on ;Yes(it means end of file name)
- pr_txt:
- jmp exit ;Jump to print message and qiut
-
- check_if_first:
- or cx,cx
- jnz move_char
- cmp al,'-'
- jnz set_args_addr
- inc si
- mov al,es:[si]
- cmp al,'l'
- jz get_char
- cmp al,'h'
- lea dx,inv_option
- jnz pr_txt
- or flags,LOAD_HIGH
- jmp get_char
- set_args_addr:
- mov args_offset,si ;Point to first char (in PSP) ...
- mov args_seg,es ; ... of the file name
-
- move_char: mov [di],al
- inc di
- inc cx
- jmp get_char
- end_of_name:
- or cx,cx
- jnz go_on
- lea dx,help_scr
- mov bx,1
- mov cx,HELP_LEN
- mov ah,40h
- int 21h
- jmp exit_no_print
- go_on:
- ;.......................................................
- ; XMS support !!!!!!
- mov ax,4300h
- int 2fh
- cmp al,80h
- jne no_xms
- mov ax,4310h
- int 2fh
- check_xms:
- cmp word ptr es:[bx],JMP_SHORT ;is it short jmp ?
- je place_jmp
-
- cmp byte ptr es:[bx],JMP_FAR ;is it jmp xxxx:yyyy ?
- jne no_xms
-
- les bx,dword ptr es:[bx + 1]
- jmp check_xms
-
- place_jmp:
- cmp word ptr es:[bx + 2],9090h ;Nop instructions ?
- jne no_xms
- or flags,OWN_XMS ;signal that XMS handler changed
- mov prv_offs,bx
- mov prv_seg,es
-
- mov xms_offs,bx
- add xms_offs,5 ;set offset to point after jmp instruction
- mov xms_seg,es
- mov ax,es:[bx + 5]
- mov word ptr old_code,ax
- mov ax,es:[bx + 7] ;save 5 bytes of code
- mov word ptr old_code + 2,ax
- mov al,es:[bx + 9]
- mov old_code + 4,al
-
- cli
- mov byte ptr es:[bx + 5],JMP_FAR ;place there jmp far to our xms handler
- mov ax,offset xms_handler
- mov word ptr es:[bx + 6],ax
- mov ax,cs
- mov word ptr es:[bx + 8],ax
- sti
-
- no_xms:
- mov drv_beg,ZERO
- mov ax,our_seg
- add ax,10h ;add PSP size (in paras)
- mov dev_seg,ax ;Set seg. address of device driver
- jmp ldrv
- ;...............................................................................
- old_code db 5 dup(0)
- CODE_LEN equ $ - old_code
-
- xms_vector label dword
- xms_offs dw 0
- xms_seg dw 0
-
- prv_vector label dword
- prv_offs dw 0
- prv_seg dw 0
-
- handle dw 0
- ;-------------------------------------------------------------------------------
- ;New XMS handdler
- ;-------------------------------------------------------------------------------
- xms_handler:
- pushf
- push ax
- push di
- push es
- les di,cs:xms_vector
- mov ax,word ptr cs:old_code ;restore previous state ...
- cli
- stosw ; ... of XMS entry ...
- mov ax,word ptr cs:old_code + 2
- stosw
- mov al,cs:old_code + 4
- stosb
- sti
- pop es
- pop di
- pop ax
-
- cmp ah,9 ;Allocate extended memory block ?
- jnz xms_jmp ;No,jump
- popf
- call cs:xms_vector ;call original XMS handler
- pushf
- or ax,ax
- jz xms_end
- mov cs:handle,dx
- xms_end:
- popf
- retf
- xms_jmp:
- popf
- call cs:xms_vector
- push es
- push bx
- push ax
- les bx,cs:xms_vector
- cli
- mov byte ptr es:[bx],JMP_FAR ;place there jmp far to our XMS handler
- mov ax,offset xms_handler
- mov word ptr es:[bx + 1],ax
- mov ax,cs
- mov word ptr es:[bx + 3],ax
- sti
- pop ax
- pop bx
- pop es
- retf
-
- ;...............................................................................
- ; restore_xms:
- ; restores previous state of original XMS handler
- ;...............................................................................
- restore_xms proc near
-
- test flags,OWN_XMS ;XMS handler changed ?
- jz res_xms_end ;No,jump
- push es
- push di
- les di,xms_vector
- mov si,offset old_code
- mov cx,CODE_LEN
- cld
- cli
- rep movsb
- sti
- pop di
- pop es
-
- res_xms_end:
- ret
- restore_xms endp
- ;...............................................................................
- ; free_xmem:
- ; frees extended memory block and replaces (in original XMS handler)
- ; JMP xxxx:yyyy with JMP_SHORT and three NOP.
- ;...............................................................................
- free_xmem proc near
-
- test flags,OWN_XMS ;XMS supported ?
- jz free_xmem_end ;no,jump to quit
-
- les bx,prv_vector
- cli
- mov word ptr es:[bx],JMP_SHORT ;place there JMP short & ...
- mov word ptr es:[bx + 2],9090h ; ... three NOPs
- mov byte ptr es:[bx + 4],90h
- sti
-
- mov dx,handle
- or dx,dx
- jz free_xmem_end
- mov ah,0ah
- call cs:xms_vector ;free memory
-
- free_xmem_end:
- ret
- free_xmem endp
-
- ;...............................................................................
- ; messages to display
- db 'Program written by Janusz Wojcik'
- err_txt db 'IDrv: That version of DOS is not supported!',cr,lf,lf,'$'
- not_PC_Dos db 'IDrv: Not PC DOS ',cr,lf,lf,'$'
- help_scr db 'usage: idrv [options] [d:\path\]filename.ext [parms]',cr,lf
- db 'options:',cr,lf
- db ' -h = load high (in UMB)',cr,lf
- db " -l = load low (default)",cr,lf
- db cr,lf
- db 'If you find this program useful please send $10 to:',cr,lf
- db ' Janusz Wojcik',cr,lf
- db ' 20-608 Lublin',cr,lf
- db ' ul.Wajdeloty 6/13',cr,lf
- db ' Poland',cr,lf
- HELP_LEN equ $ - help_scr
- inv_option db 'IDrv: invalid option! ',cr,lf,lf,'$'
- header db 'Device Drivers Installer v1.06',cr,lf
- db '(C) 1990 by Janusz Wojcik Lublin,Poland.',cr,lf,lf,'$'
- ;....................................................................................
- LEN equ $ - new_seg
-
- code ENDS
- END start