home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / SYSTEM / IDRV01.ZIP / IDRV.ASM next >
Encoding:
Assembly Source File  |  1991-11-25  |  25.3 KB  |  1,042 lines

  1.  
  2. NAME    Device_Driver_Installer
  3. TITLE    Idrv.asm
  4. ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;
  5. ;                              18-11-1991           ;
  6. ;    Idrv.asm (v1.06)                                   ;
  7. ;    compiled with Turbo Assembler v1.0                           ;
  8. ;                        by Janusz Wojcik            ;
  9. ;                        Lublin,Poland.               ;
  10. ;..............................................................................;
  11.  
  12.  
  13.         ASSUME DS:st_seg, SS:st_seg ,CS:st_seg ,ES:st_seg
  14. st_seg        SEGMENT    
  15.         ORG    100h
  16.  
  17. start:        
  18.         mov    ax,es
  19.         dec    ax
  20.         mov    es,ax            ;ES = ES - 1
  21.         mov    ax,word ptr es:3    ;get size of memory block from MCB
  22.         push    ax
  23.         mov    bx,es
  24.         add    ax,bx            ;compute address of the end of memory block
  25.         mov    bx,LEN + 15        ;compute size of the program ...
  26.         mov    cl,4
  27.         shr    bx,cl            ; ... in paragraphs
  28.         sub    ax,bx            ;calculate new address of program's beginning
  29.  
  30.         mov    jmp_seg,ax        ;save it
  31.         mov    es,ax
  32.             ;.......................................................
  33.         pop    ax
  34.         mov    dx,10h                 ;add PSP size
  35.         add    dx,bx
  36.         sub    ax,dx
  37.         cmp    ax,1000h        ;some drivers set stack at the ...
  38.                         ; ... end of the segment !!!
  39.         ja    move_code        ;jump if more than 64KB left
  40.         lea    dx,too_small
  41.         mov    ah,9
  42.         int    21h
  43.  
  44.         mov    ah,4ch        ;EXIT
  45.         mov    al,1        ;Set return code
  46.         int    21h
  47.             ;.......................................................
  48. move_code:
  49.         mov    cx,LEN
  50.         mov    di,0
  51.         mov    si,offset pr_end
  52.         cld
  53.         rep    movsb            ;move program into upper memory
  54.     
  55.         jmp    dword ptr jmp_offs        ;and go there
  56.  
  57. too_small    db    'IDrv: Too small memory!',cr,lf,lf,'$'
  58.  
  59. jmp_offs    dw    0
  60. jmp_seg        dw    0
  61.  
  62. ALIGN        16
  63. pr_end        equ    $
  64.  
  65. st_seg        ends
  66. ;*******************************************************************************
  67.  
  68.         ASSUME DS:code, SS:code ,CS:code ,ES:code
  69. code        SEGMENT    Byte Public 'code'
  70.     
  71. new_seg        equ    $
  72.         mov    ax,cs
  73.         cli
  74.         mov    ss,ax            ;Set own stack
  75.         mov    sp,offset EOS
  76.         sti
  77.  
  78.         mov    ax,ds
  79.         push    cs
  80.         pop    ds            ;DS = CS
  81.         mov    our_seg,ax
  82.  
  83.         jmp    starter        ; jump over data
  84. own_stack    db    157 dup(0)
  85. EOS        equ    $        ; End Of Stack
  86.  
  87.  
  88. ;...............................................................................
  89.  
  90. device_header    struc
  91. next_offs    dw    ?
  92. next_seg    dw    ?
  93. dev_attr    dw    ?
  94. dev_strategy    dw    ?
  95. dev_interrupt    dw    ?
  96. name_unit    db    8 dup(?)
  97. device_header    ends
  98.  
  99. ;Idrv Control Block
  100. icb        struc
  101. signature    db    7 dup(?)
  102. xms_marker    db    3 dup(?)
  103. prv_xms_offs    dw    ?
  104. prv_xms_seg    dw    ?
  105. xms_handle    dw    ?
  106. icb        ends
  107. .errnz        16 - SIZE icb
  108. ;...............................................................................
  109.  
  110. lf        equ    0ah        ; line feed
  111. cr        equ    0dh        ; carriage return
  112.  
  113. ZERO        equ    0
  114. INIT        equ    0
  115. TAB        equ    9
  116.  
  117. DIB_SIZE    equ    21h
  118. FIRST_DIB    equ    26h
  119. FIRST_DA    equ    3ch
  120. NUM_OF_DRV    equ    46h
  121. TOTAL_NUM    equ    47h
  122. MAX_SECTOR    equ    36h
  123. JMP_SHORT    equ    3ebh
  124. JMP_FAR        equ    0eah
  125.  
  126. ;...............................................................................
  127. ;    the program body
  128. ;..............................................................................        
  129. ldrv:  
  130.         call    load_drv
  131.         jnc    idev
  132.         jmp    exit
  133.  
  134. idev:        
  135.         mov    es,dos_seg
  136.         mov    al,byte ptr es:NUM_OF_DRV    ;Get real number of drives
  137.         mov     drive_num,al        ;Set unit number in Req. Header
  138.         call    init_dev        ;INIT device
  139.         jnc    modify_mem
  140.         call    restore_xms        ;restore previous state of original XMS handler
  141.         lea    dx,err3
  142.         jmp    exit
  143. modify_mem:    
  144.         call    restore_xms        ;restore previous state of original XMS handler
  145.         test    flags,UMB_USED        ;Driver in other mem. block ?
  146.         jz    create_cb        ;No,skip
  147.         mov    bx,ending_offset
  148.         add    bx,15
  149.         rcr    bx,1
  150.         mov    cl,3
  151.         shr    bx,cl
  152.         add    bx,ending_segment
  153.         mov    ax,dev_seg
  154.         dec    ax            ;take into account ICB size!
  155.         sub    bx,ax            ;BX - size of mem. block in paragraphs
  156.         mov    es,ax            ;ES - seg. of the block
  157.         mov    ah,4ah            ;Modify alloc. mem. block
  158.         int    21h
  159.         jnc    create_cb
  160.         lea    dx,err7
  161.         jmp    exit_err
  162. create_cb:
  163.         mov    ax,dev_seg
  164.         mov    es,ax
  165.         mov    bx,drv_beg
  166.         call    create_icb        ;create Idrv Control Block                     
  167.         mov    ax,es:dev_attr[bx]
  168.         test    ah,80h            ;Character device ?
  169.         jnz    ldev            ;Yes,jump to link device headers
  170.         cmp    units,ZERO        ;Error during INIT ?
  171.         jnz    check_CDS        ;No
  172.         lea    dx,err3
  173.         jmp    exit            ;Yes,jump to quit
  174. check_CDS:
  175.         call    check_DA
  176.         jc    exit_err
  177. DIB_creation:        
  178.         call    seek_last        ;Seek the last DIB
  179.         mov    lastDIB_offs,bx
  180.         mov    lastDIB_seg,es
  181.  
  182.         test    flags,UMB_USED        ;driver in other mem.block ?
  183.         jz    DIB_after_drv        ;No,jump
  184.         mov    ax,our_seg
  185.         add    ax,10h            ;add PSP size
  186.         jmp    set_DIB_addr
  187.  
  188. DIB_after_drv:
  189.         mov    ax,ending_offset
  190.         add    ax,15
  191.         mov    cl,4
  192.         shr    ax,cl
  193.         add    ax,ending_segment
  194. set_DIB_addr:
  195.         mov    DIB_seg,ax
  196.         mov    DIB_offs,ZERO
  197.         
  198.         mov    cl,units        ;CX = number of units
  199.         xor    ch,ch
  200.         mov    dl,es:[bx]        ;DL = last drive#
  201.         mov    dh,0ffh
  202. DIB_continue:        
  203.         inc    dl            ;Set drive#
  204.         inc    dh            ;Set unit#
  205.         call    create_DIB        ;Create Disk Info Block
  206.         jnc    DA_creation
  207.         call    restore            ;Restore previous state of DIB & DA chains
  208.         jmp    exit_err
  209. DA_creation:
  210.         call    create_DA            ;Create Disk Area
  211.         les    bx,dword ptr DIB_offs
  212.         add    DIB_offs,DIB_SIZE            ;Set new DIB address
  213.         loop    DIB_continue
  214.                 
  215. ldev:        call    link_dev        ;Link device headers
  216.         jmp    exit_OK
  217. exit_err:
  218.         call    free_xmem
  219.         call    print_msg        
  220.  
  221. exit_OK:
  222.         mov    ax,our_seg
  223.         mov    es,ax
  224.         mov    es,es:2ch
  225.         mov    ah,49h        ; Free allocated memory (environment)
  226.         int    21h
  227.  
  228.         test    flags,UMB_USED    ; Driver in UMB ?
  229.         jz    drv_not_high    ; No,jump
  230.         mov    dx,100h        ; size of PSP
  231.         add    dx,ad_mem
  232.         add    dx,15
  233.         rcr    dx,1
  234.         mov    cl,3
  235.         shr    dx,cl
  236.         jmp    term_resident
  237.  
  238. drv_not_high:        
  239.         mov    dx,ending_offset    ;Compute address of ...
  240.         add    dx,ad_mem
  241.         add    dx,15
  242.         rcr    dx,1
  243.         mov    cl,3
  244.         shr    dx,cl
  245.  
  246.         add    dx,ending_segment
  247.         inc    dx            ; (add one para)
  248.         mov    ax,our_seg
  249.         sub    dx,ax            ; ... program end
  250. term_resident:
  251.         xor    al,al        ; set 0 for return code
  252.         mov    ah,31h        ;Terminate and remain resident
  253.         int    21h
  254.  
  255. exit:
  256.         call    print_msg
  257. exit_no_print:
  258.         mov    ah,4ch        ;EXIT
  259.         mov    al,1        ;Set return code
  260.         int    21h
  261. ;..............................................................................
  262. ; create_icb:
  263. ;    creates Idrv Control Block before Device Header
  264. ; Input:
  265. ;    ES:BX - Device Header address
  266. ;..............................................................................
  267. create_icb    proc    near
  268.  
  269.         push    es
  270.         mov    ax,es
  271.         dec    ax
  272.         mov    es,ax
  273.         mov    si,offset sign
  274.         mov    cx,SIG_LEN
  275.         mov    di,bx
  276.         cld
  277.         rep    movsb                ;place signature
  278.         mov    ax,handle
  279.         mov    word ptr es:xms_marker[bx],ax    ;the word will be ...
  280.                             ; ... 0 if handle is 0
  281.         cmp    ax,ZERO
  282.         je    xms_not_used
  283.         mov    word ptr es:xms_handle[bx],ax
  284.         mov    byte ptr es:xms_marker[bx],'X'    ;signal that XMS was used
  285.         mov    word ptr es:xms_marker[bx + 1],'SM'
  286.         mov    ax,prv_offs
  287.         mov    word ptr es:prv_xms_offs[bx],ax
  288.         mov    ax,prv_seg
  289.         mov    word ptr es:prv_xms_seg[bx],ax
  290. xms_not_used:
  291.         pop    es
  292.         ret
  293. create_icb    endp
  294.  
  295. page;..........................................................................
  296. ; link_dev:                                .......
  297. ;    links Device Header of the driver with the chain of             .......
  298. ;    Device Headers of the rest  drivers                .......                    .......
  299. ;..............................................................................
  300.  
  301.  
  302. link_dev:
  303.         mov    es,dos_seg
  304.         mov    si,48h
  305.         push    es
  306.         les    si,dword ptr es:[si]    ;Address of next dev. header
  307.         mov    bx,drv_beg
  308.         mov    ax,dev_seg
  309.         push    ds
  310.         mov    ds,ax
  311.         mov    next_offs[bx],si
  312.         mov    next_seg[bx],es
  313.         mov    bx,dev_attr[bx]        ;get dev.attribute for later
  314.         pop    ds
  315.  
  316.         pop    es
  317.         cli
  318.         mov    es:48h,word ptr ZERO
  319.         mov    ax,dev_seg
  320.         mov    es:4ah,ax            
  321.         sti
  322.     
  323.         test    bl,1            ;Is it Stdin device ?
  324.         jz    test_clk        ;No,jump
  325.         mov    es:32h,word ptr ZERO    ;Change pointer to ...
  326.         mov    es:34h,ax        ; ... Stdin
  327.         les    bx,es:02ah        ;Get address of DOS file table
  328.         add    bx,dos_dep        ;change entry length of OFT if necessary
  329.         mov    es:[bx + 042h],word ptr ZERO    ;Change address of dev.header ...
  330.         mov    es:[bx + 044h],ax        ; ... in Open Files Table
  331.         jmp    quit_link
  332.  
  333. test_clk:    test    bl,8            ;Is it clock device ?
  334.         jz    quit_link        ;No,jump
  335.         mov    es:2eh,word ptr ZERO
  336.         mov    es:30h,ax
  337.         
  338. quit_link:
  339.         ret        
  340.         
  341. ;..............................................................................
  342. ; load_drv:                                .......
  343. ;    loads device driver code into memory                .......
  344. ;..............................................................................
  345. load_drv:    
  346.         call    get_file_len
  347.         jc    quit_load
  348.         call    alloc_umb
  349.         mov    ax,dev_seg
  350.         xor    dx,dx
  351.         push    ds         
  352.         mov    ds,ax        ;DS:DX - buffer address
  353.         mov    ah,3fh        ;READ
  354.         int    21h
  355.         pop    ds
  356.         lea    dx,err12
  357.         jc    quit_load
  358.  
  359.         mov    ah,3eh        ;CLOSE
  360.         int    21h
  361. quit_load:    
  362.         ret        
  363. ;...............................................................................
  364. ;  get_file_len:
  365. ;    checks file length.
  366. ;  OUTPUT:
  367. ;    BX - file handle
  368. ;    CX - file length
  369. ;...............................................................................
  370. get_file_len    proc    near
  371.         mov    ah,3dh        ;OPEN
  372.         mov    dx,offset fname
  373.         mov    al,0
  374.         int    21h
  375.         lea    dx,err10
  376.         jc    quit_get
  377.  
  378.         mov    bx,ax        ;save file handle
  379.         mov    ah,42h        ;LSEEK ...
  380.         mov    al,2        ; ... to the end of file
  381.         mov    cx,ZERO
  382.         mov    dx,ZERO
  383.         int    21h
  384.         jnc    get_cont1
  385.         lea    dx,err11
  386.         jmp    quit_get
  387. get_cont1:        
  388.         or    dx,dx        ;DX:AX - file length
  389.         jz    get_cont2
  390.         stc
  391.         lea    dx,err13
  392.         jmp    quit_get
  393. get_cont2:
  394.         push    ax
  395.         mov    ah,42h        ;LSEEK ...
  396.         mov    al,0        ; ... to the beginning
  397.         xor    cx,cx        
  398.         xor    dx,dx
  399.         int    21h
  400.         lea    dx,err11
  401.         pop    cx
  402. quit_get:
  403.         ret
  404. get_file_len    endp
  405. ;...............................................................................
  406. ; alloc_umb:
  407. ;    allocates Upper Memory Block if necessary
  408. ; INPUT:
  409. ;     CX - file size in bytes
  410. ;...............................................................................
  411. alloc_umb:
  412.         test    flags,DOS_V5    ;DOS v5.xx and load high ?
  413.         jz    alloc_end    ;No,jump
  414.         test    flags,LOAD_HIGH    
  415.         jz    alloc_end    ;No,jump
  416.         push    bx
  417.         push    cx        ;save size of the file
  418.  
  419.         mov    ax,5800h        ;get memory allocation flags
  420.         int    21h
  421.         mov    mem_flag,al        ;save flags
  422.  
  423.         mov    ax,5802h        ;get link status
  424.         int    21h
  425.         mov    link_stat,al
  426.  
  427.         mov    ax,5801h        ;search upper mem. for first fit
  428.         mov    bx,80h
  429.         int    21h
  430.  
  431.         mov    ax,5803h        ;set link status
  432.         mov    bx,1
  433.         int    21h
  434.         jc    restore_alloc_flag
  435.  
  436.         mov    bx,cx          ;BX = file size
  437.         add    bx,0fh
  438.         rcr    bx,1
  439.         mov    cx,3
  440.         shr    bx,cl        ;BX = size of mem. in paragraphs
  441.         inc    bx        ;add one paragraph for ICB 
  442.         mov    ah,48h        ;allocate memory
  443.         int    21h
  444.         jc    restore_alloc_flag
  445.         inc    ax        ;driver will be placed after ICB
  446.         mov    dev_seg,ax
  447.         or    flags,UMB_USED    ;driver is in other mem. block
  448. restore_alloc_flag:
  449.         xor    bh,bh
  450.         mov    bl,mem_flag
  451.         mov    ax,5801h    ;restore allocation flags
  452.         int    21h
  453.  
  454.         mov    ax,5803h    ;restore link status
  455.         xor    bh,bh
  456.         mov    bl,link_stat
  457.         int    21h
  458.  
  459.         pop    cx
  460.         pop    bx
  461. alloc_end:
  462.         ret
  463.         
  464.         
  465. ;...............................................................................
  466. ; init_dev:
  467. ;    calls Strategy and Interrupt Routines of the device driver
  468. ;...............................................................................
  469. init_dev:
  470.         mov    si,drv_beg
  471.         mov    ax,dev_seg
  472.         mov    es,ax
  473.         mov    ax,es:dev_strategy[si]    ;get addr. of strategy routine
  474.         mov    dev_offs,ax
  475.         mov    ax,es:dev_interrupt[si] ;get addr. of interrupt routine
  476.         push    ax            ;save it for later
  477.  
  478.         push    cs
  479.         pop    es            ;ES = CS
  480.         mov    bx,offset Request_Header  ;ES:BX - Request Header
  481.  
  482.         call    dword ptr dev_offs    ;Call dev. strategy routine
  483.         
  484.         pop    ax
  485.         mov    dev_offs,ax
  486.  
  487.         call    dword ptr dev_offs    ;Call dev. interrupt routine
  488.         mov    ax,ending_offset
  489.         or    ax,ax
  490.         jnz    quit_init
  491.         mov    ax,ending_segment
  492.         cmp    ax,dev_seg
  493.         ja    quit_init
  494.         stc
  495.         ret
  496. quit_init:       
  497.         clc            
  498.         ret
  499. ;...............................................................................        
  500. ; print_msg:
  501. ;    displays the message.
  502. ; INPUT:
  503. ;     DS:DX - pointer to the character string
  504. ;...............................................................................
  505. print_msg:    
  506.         mov    ah,9
  507.         int    21h
  508.         ret
  509. ;...............................................................................        
  510. ; seek_last:
  511. ;    seeks the last Disk Info Block
  512. ; OUTPUT:
  513. ;    ES:BX - last DIB
  514. ;...............................................................................
  515. seek_last    proc    near
  516.  
  517.         mov    es,dos_seg
  518.         les    bx,es:FIRST_DIB            ;Get address of first DIB
  519.         mov    si,dos_dep3        
  520. next_DIB:    cmp    word ptr es:[si + bx + 18h],0ffffh    ;The last DIB ?
  521.         jz    seek_end                ;Yes,jump
  522.         les    bx,dword ptr es:[si + bx + 18h]        ;Get addr. of next DIB
  523.         jmp    next_DIB
  524. seek_end:    ret        
  525.         
  526. seek_last    endp
  527. ;................................................................................
  528. ; create_DIB:
  529. ;     creates Disk Info Block for the drive
  530. ; INPUT:
  531. ;    ES:BX - last DIB
  532. ;    DL - drive#
  533. ;    DH - unit#
  534. ;
  535. ; OUTPUT:
  536. ;    ES:BX - address of created DIB 
  537. ;................................................................................
  538. create_DIB    proc    near
  539.  
  540.  
  541.         push    ds
  542.         
  543.         mov    ax,DIB_offs
  544.         mov    si,dos_dep3
  545.         mov    word ptr es:[si + bx + 18h],ax    ;Chain ...
  546.         mov    ax,DIB_seg            ; ...
  547.         mov    word ptr es:[si + bx + 1ah],ax    ; ... DIBs
  548.  
  549.         les     bp,dword ptr DIB_offs          ;ES:BP - next DIB address
  550.         mov    word ptr es:[bp],dx        ;Set drive and unit #
  551.         mov    word ptr es:[si + bp + 18h],0ffffh    ;Mark it as the last DIB
  552.         mov    byte ptr es:[si + bp + 17h],0ffh    ;Init access flag
  553.         mov    word ptr es:[si + bp + 12h],ZERO    ;Set address of ...
  554.         mov    ax,dev_seg
  555.         mov    word ptr es:[si + bp + 14h],ax    ; ... device header
  556.  
  557.         lds    si,dword ptr args_offset    ;DS:SI = pointer to BPB
  558.         push    ax
  559.         mov    al,dh
  560.         xor    ah,ah
  561.         mul    cs:two
  562.         add    si,ax
  563.         mov    si,[si]                ;Get BPB address
  564.         pop    ds                ;DS = driver segment
  565.         mov    ah,53h    
  566.         int    21h                ;Build DIB
  567.         mov    ax,es:[bp + 2]            ;Get sector size from DIB
  568.         mov    es,cs:dos_seg
  569.         add    cs:ad_mem,DIB_SIZE            ;Add DIB size
  570.         cmp    ax,es:MAX_SECTOR        ;Compare it with max. sector size
  571.         jbe    create_ok            ;If smaller than OK
  572. ;        les     bp,dword ptr cs:DIB_offs    ;ES:BP - current DIB address
  573. ;        dec    byte ptr es:[bp]        ;decrement drive number
  574.         lea    dx,err5
  575.         stc
  576.         jmp    drop_regs
  577. create_ok:    clc        
  578.         
  579. drop_regs:
  580.         pop    ds
  581.         ret
  582.         
  583. create_DIB    endp
  584. ;...............................................................................
  585. ; create_DA:
  586. ;    creates Drive Area (or else Current Directory Structure) for the drive
  587. ;...............................................................................
  588. create_DA    proc    near
  589.         
  590.         push    cx
  591.         push    dx
  592.         
  593.         mov    es,dos_seg
  594.         inc    byte ptr es:NUM_OF_DRV        ;Increase real number of drives
  595.         mov    al,byte ptr es:NUM_OF_DRV
  596.         call    get_DA_addr
  597.         add    al,40h                ;Convert to ASCI letter
  598.         mov    es:[di],al            ;Put it into DA 
  599.         add    di,43h    
  600.         mov    ax,4000h            ;Signal that drive exists
  601.         stosw
  602.         mov    ax,DIB_offs        
  603.         stosw                    ;Set DIB offset
  604.         mov    ax,DIB_seg
  605.         stosw                    ;Set DIB segment
  606.         mov    ax,0
  607.         stosw
  608.         mov    ax,0ffffh
  609.         stosw
  610.         stosw
  611.         mov    ax,2
  612.         stosw
  613. create_end:        
  614.         pop    dx
  615.         pop    cx
  616.         
  617.         ret
  618.         
  619. create_DA    endp        
  620. ;...............................................................................;        
  621. ; get_DA_addr:
  622. ;    calculates address of Drive Area for drive AL
  623. ; INPUT:
  624. ;    AL - drive number,eg. 1 - A:, 2 - B:, ...
  625. ;
  626. ; OUTPUT:                                    ;
  627. ;    ES:DI - address of Drive Area for drive AL                ;
  628. ;...............................................................................;
  629. get_DA_addr    proc    near
  630.  
  631.         push     ax
  632.         push    dx
  633.         dec    al
  634.         xor    ah,ah
  635.         mov    dl,51h                ;Set DA ...
  636.         add    dl,dos_dep2            ; ... size
  637.         mul    dl                ;Multiply by DA size
  638.         mov    es,dos_seg
  639.         les    di,dword ptr es:FIRST_DA    ;Get addr. of first DA
  640.         add    di,ax                ;So now ES:DI points to new DA
  641.         pop    dx
  642.         pop    ax
  643.         ret
  644.         
  645. get_DA_addr    endp
  646. ;...............................................................................
  647. ; check_DA:
  648. ;    checks whether already installed devices are not network or SUBSTed ones
  649. ;...............................................................................
  650. check_DA    proc    near
  651.  
  652.         mov    es,dos_seg
  653.         mov    al,byte ptr es:NUM_OF_DRV    ;Get real number of drives
  654.         xor    ch,ch
  655.         mov    cl,units
  656.         mov    ah,byte ptr es:TOTAL_NUM    ;Get total number of drives
  657. check_next_DA:
  658.         inc    al
  659.         cmp    al,ah
  660.         lea    dx,err4
  661.         ja    check_err_end
  662.         call    get_DA_addr            ;Get address of DA to ES:DI
  663.         cmp    word ptr es:[di + 43h],ZERO    ;DA not used ?
  664.         jz    check_loop            ;Yes,jump
  665.         lea    dx,err6
  666. check_err_end:    
  667.         stc                    ;Signal error
  668.         ret        
  669. check_loop:
  670.         loop    check_next_DA
  671.         clc
  672.         ret
  673.         
  674. check_DA    endp
  675. ;................................................................................
  676. ; restore:
  677. ;    restores previous state of Drive Area 
  678. ;................................................................................
  679. restore        proc    near
  680.         
  681.         les    bx,dword ptr lastDIB_offs
  682.         mov    si,dos_dep3
  683.         mov    word ptr es:[si + bx + 18h],0ffffh    ;Mark it as the last DIB
  684.         mov    al,es:[bx]            ;Get last drive nimber
  685.         inc    al
  686.         mov    es,dos_seg
  687.         mov    ah,byte ptr es:NUM_OF_DRV    ;Get real number of drives
  688.         mov    byte ptr es:NUM_OF_DRV,al    ;Restore real number of drives
  689. cmp_numb:
  690.         cmp    ah,al
  691.         jz    restore_end
  692.         inc    al
  693.         call    get_DA_addr            ;Get address of DA to ES:DI
  694.         mov    word ptr es:[di + 43h],ZERO    ;Mark DA as not used 
  695.         jmp    cmp_numb
  696. restore_end:
  697.         ret
  698.  
  699. restore     endp
  700. ;.................................................................................
  701. two        db    2        ;byte = 2h
  702.  
  703. DOS_V5        equ    1
  704. UMB_USED    equ    2
  705. LOAD_HIGH    equ    4
  706. OWN_XMS        equ    8
  707.  
  708. flags        db    0    ;B0 set if DOS v5.xx
  709.                 ;B1 set if UMB used
  710.                 ;B2 set if driver is to be load high
  711.                 ;B3 set if XMS handler changed
  712.  
  713. mem_flag    db    0    ;memory allocation flag
  714. link_stat    db    0    ;UMB link status
  715.  
  716. dos_dep        dw    0    ;0 - if dos 3.xx, 6 - if dos 4.xx or 5.xx
  717. dos_dep2    db    0    ;0 - if dos 3.xx, 7 - if dos 4.xx or 5.xx
  718. dos_dep3    dw    0    ;0 - if dos 3.xx, 1 - if dos 4.xx or 5.xx
  719.  
  720. dos_seg        dw    0        ;IMBDOS segment
  721. our_seg        dw    0        ;our initial segment
  722. ad_mem        dw    0        ;Mem. occupied by DIBs
  723. drv_beg        dw    0        ;Start of driver (must be on para boundry)
  724. drv_seg        dw    0        ;Segment addr. of driver
  725.         
  726. dev_offs    dw    0        ;Pointer to driver ...
  727. dev_seg        dw    0        ; ... strat/interr routine
  728.  
  729. DIB_offs    dw    0        ;Address of ...
  730. DIB_seg        dw    0        ; ... driver's DIB
  731.  
  732. lastDIB_offs    dw    0        ;Address of ...
  733. lastDIB_seg    dw    0        ; ... the last DIB
  734.                 
  735. Request_Header  label    byte
  736. header_length    db    HLEN
  737. unit_code    db    ?
  738. command_code    db    INIT
  739. status        dw    0
  740. reserved    dq    0
  741.  
  742. units        db    ?
  743. ending_offset    dw    ?
  744. ending_segment    dw    ?
  745. args_offset    dw    ?
  746. args_seg    dw    ?
  747. drive_num    db    ?
  748. HLEN        equ    $ - header_length
  749. error_msg    dw    0        ;used by DOS v4.xx
  750. HLEN2        equ    $ - header_length
  751.  
  752. sign        db    'IdrvCB '
  753. SIG_LEN        equ    $ - sign
  754.  
  755. ;...............................................................................        
  756. fname        db    128 dup (0)
  757.  
  758. err3        db    'IDrv: INIT error!',cr,lf,lf,'$'
  759. err4        db    'IDrv: Too small LASTDRIVE specified!',cr,lf,lf,'$'
  760. err5        db    'IDrv: Sector size too large!',cr,lf,lf,'$'
  761. err6        db    "IDrv: Can't install device after SUBSTed and network device!",cr,lf,lf,'$'
  762. err7        db    'IDrv: Memory allocation error!',cr,lf,lf,'$'
  763. ;...............................................................................
  764. err10        db    'IDrv: File not found!',cr,lf,lf,'$'
  765. err11        db    'IDrv: SEEK error!',cr,lf,lf,'$'
  766. err12        db    'IDrv: READ error!',cr,lf,lf,'$'
  767. err13        db    'IDrv: File too large!',cr,lf,lf,'$'
  768. ;...............................................................................
  769.  
  770.  
  771. starter:    lea    dx,header
  772.         call    print_msg    
  773.         mov    ah,30h
  774.         int    21h            ;Get DOS version number
  775.         lea    dx,err_txt
  776.         cmp    al,3
  777.         jb    pr_txt
  778. check_ver:
  779.         je    get_list        ;DOS v3.xx
  780.         cmp    al,5            ;ver. above 5 ?
  781.         ja    pr_txt            ;yes,jump
  782.         jne    dos_v4
  783.         or    flags,DOS_V5        ;DOS v5.xx
  784. dos_v4:
  785.         mov    dos_dep,6        ;No,change entry length of Open Files Table 
  786.         mov    dos_dep2,7        ;Change entry length of Drive Area
  787.         mov    dos_dep3,1        ;Change entry length of Disk Info Block
  788.         mov    header_length,HLEN2    ;Increase header length
  789. get_list:
  790.         mov    ah,52h
  791.         int    21h            ;Get vector for int 25H
  792.         mov    dos_seg,es
  793.         lea    dx,not_PC_Dos
  794.         cmp    word ptr es:52h,'UN'    ;NUL device ?
  795.         jne    pr_txt            ;No,jump
  796.         les    di,dword ptr es:02ah    ;get address of DOS file table
  797.         add    di,dos_dep        ;change entry length of OFT if necessary
  798.         cmp    byte ptr es:[di + 05bh],'C'    ;Entry for dev. CON ?
  799.         jne    pr_txt
  800.         cmp    word ptr es:[di + 05ch],'NO'    
  801.            jne    pr_txt
  802.  
  803.         mov    si,80h
  804.         mov    ax,our_seg
  805.         mov    es,ax
  806.         mov    di,offset fname
  807.         xor    cx,cx
  808. get_char:    inc    si
  809.         mov    al,es:[si]
  810.         cmp    al,CR
  811.         jz    end_of_name
  812.         cmp    al,TAB        ;Is it Tab ?
  813.         jz    is_any        ;Yes,jump
  814.         cmp    al,' '        ;Is it space ?
  815.         jnz    check_if_first    ;No,jump
  816. is_any:        
  817.         or    cx,cx        ;Any char moved ?
  818.         jz    get_char    ;No,jump to get next char
  819.         jmp    go_on        ;Yes(it means end of file name)
  820. pr_txt:    
  821.         jmp    exit        ;Jump to print message and qiut
  822.  
  823. check_if_first:
  824.         or    cx,cx
  825.         jnz    move_char
  826.         cmp    al,'-'
  827.         jnz    set_args_addr
  828.         inc    si
  829.         mov    al,es:[si]
  830.         cmp    al,'l'
  831.         jz    get_char
  832.         cmp    al,'h'
  833.         lea    dx,inv_option
  834.         jnz    pr_txt
  835.         or    flags,LOAD_HIGH
  836.         jmp    get_char        
  837. set_args_addr:
  838.         mov    args_offset,si  ;Point to first char (in PSP) ... 
  839.         mov    args_seg,es    ; ... of the file name
  840.         
  841. move_char:    mov    [di],al
  842.         inc    di
  843.         inc    cx
  844.         jmp    get_char
  845. end_of_name:        
  846.         or    cx,cx
  847.         jnz    go_on
  848.         lea    dx,help_scr
  849.         mov    bx,1
  850.         mov    cx,HELP_LEN
  851.         mov    ah,40h
  852.         int    21h
  853.         jmp    exit_no_print
  854. go_on:    
  855.             ;.......................................................
  856.             ; XMS support !!!!!!
  857.         mov    ax,4300h
  858.         int    2fh
  859.         cmp    al,80h
  860.         jne    no_xms
  861.         mov    ax,4310h
  862.         int    2fh
  863. check_xms:
  864.         cmp    word ptr es:[bx],JMP_SHORT    ;is it short jmp ?
  865.         je    place_jmp
  866.         
  867.         cmp    byte ptr es:[bx],JMP_FAR    ;is it jmp xxxx:yyyy ?
  868.         jne    no_xms
  869.         
  870.         les    bx,dword ptr es:[bx + 1]
  871.         jmp    check_xms
  872.         
  873. place_jmp:
  874.         cmp    word ptr es:[bx + 2],9090h    ;Nop instructions ?
  875.         jne    no_xms    
  876.         or    flags,OWN_XMS            ;signal that XMS handler changed
  877.         mov    prv_offs,bx
  878.         mov    prv_seg,es
  879.  
  880.         mov    xms_offs,bx
  881.         add    xms_offs,5        ;set offset to point after jmp instruction
  882.         mov    xms_seg,es
  883.         mov    ax,es:[bx + 5]
  884.         mov    word ptr old_code,ax
  885.         mov    ax,es:[bx + 7]         ;save 5 bytes of code
  886.         mov    word ptr old_code + 2,ax
  887.         mov    al,es:[bx + 9]
  888.         mov    old_code + 4,al
  889.         
  890.         cli
  891.         mov    byte ptr es:[bx + 5],JMP_FAR   ;place there jmp far to our xms handler
  892.         mov    ax,offset xms_handler
  893.         mov    word ptr es:[bx + 6],ax
  894.         mov    ax,cs
  895.         mov    word ptr es:[bx + 8],ax
  896.         sti
  897.  
  898. no_xms:        
  899.         mov    drv_beg,ZERO        
  900.         mov    ax,our_seg
  901.         add    ax,10h            ;add PSP size (in paras)
  902.         mov    dev_seg,ax        ;Set seg. address of device driver
  903.         jmp    ldrv 
  904. ;...............................................................................
  905. old_code    db    5 dup(0)
  906. CODE_LEN    equ    $ - old_code
  907.  
  908. xms_vector    label    dword
  909. xms_offs    dw    0
  910. xms_seg        dw     0
  911.  
  912. prv_vector    label    dword
  913. prv_offs    dw    0
  914. prv_seg        dw     0
  915.  
  916. handle        dw    0
  917. ;-------------------------------------------------------------------------------
  918. ;New XMS handdler            
  919. ;-------------------------------------------------------------------------------    
  920. xms_handler:
  921.         pushf
  922.         push    ax
  923.         push    di
  924.         push    es
  925.         les    di,cs:xms_vector
  926.         mov    ax,word ptr cs:old_code        ;restore previous state ...
  927.         cli
  928.         stosw                    ; ... of XMS entry ...
  929.         mov    ax,word ptr cs:old_code + 2
  930.         stosw
  931.         mov    al,cs:old_code + 4
  932.         stosb
  933.         sti
  934.         pop    es
  935.         pop    di
  936.         pop    ax
  937.  
  938.         cmp    ah,9                ;Allocate extended memory block ?
  939.         jnz    xms_jmp                ;No,jump
  940.         popf
  941.         call    cs:xms_vector             ;call original XMS handler
  942.         pushf
  943.         or    ax,ax
  944.         jz    xms_end
  945.               mov    cs:handle,dx
  946. xms_end:
  947.         popf
  948.         retf
  949. xms_jmp:
  950.         popf
  951.         call    cs:xms_vector
  952.         push    es
  953.         push    bx
  954.         push    ax
  955.         les    bx,cs:xms_vector
  956.         cli
  957.         mov    byte ptr es:[bx],JMP_FAR   ;place there jmp far to our XMS handler
  958.         mov    ax,offset xms_handler
  959.         mov    word ptr es:[bx + 1],ax
  960.         mov    ax,cs
  961.         mov    word ptr es:[bx + 3],ax
  962.         sti
  963.         pop    ax
  964.         pop    bx
  965.         pop    es        
  966.         retf
  967.     
  968. ;...............................................................................
  969. ; restore_xms:
  970. ;    restores previous state of original XMS handler
  971. ;...............................................................................    
  972. restore_xms    proc    near
  973.  
  974.         test    flags,OWN_XMS        ;XMS handler changed ?
  975.         jz    res_xms_end        ;No,jump
  976.         push    es
  977.         push    di
  978.         les    di,xms_vector
  979.         mov    si,offset old_code
  980.         mov    cx,CODE_LEN
  981.         cld
  982.         cli
  983.         rep    movsb
  984.         sti
  985.         pop    di
  986.         pop    es
  987.  
  988. res_xms_end:
  989.         ret
  990. restore_xms    endp
  991. ;...............................................................................
  992. ; free_xmem:
  993. ;    frees extended memory block and replaces (in original XMS handler)
  994. ;    JMP xxxx:yyyy with JMP_SHORT and three NOP.
  995. ;...............................................................................
  996. free_xmem    proc    near
  997.  
  998.         test    flags,OWN_XMS        ;XMS supported ?
  999.         jz    free_xmem_end        ;no,jump to quit
  1000.  
  1001.         les    bx,prv_vector
  1002.         cli
  1003.         mov    word ptr es:[bx],JMP_SHORT    ;place there JMP short & ...
  1004.         mov    word ptr es:[bx + 2],9090h    ; ... three NOPs
  1005.         mov    byte ptr es:[bx + 4],90h
  1006.         sti
  1007.  
  1008.         mov    dx,handle
  1009.         or    dx,dx
  1010.         jz    free_xmem_end
  1011.         mov    ah,0ah
  1012.         call    cs:xms_vector        ;free memory
  1013.  
  1014. free_xmem_end:
  1015.         ret
  1016. free_xmem    endp
  1017.  
  1018. ;...............................................................................
  1019. ;    messages to display
  1020.         db    'Program written by Janusz Wojcik'
  1021. err_txt        db    'IDrv: That version of DOS is not supported!',cr,lf,lf,'$'
  1022. not_PC_Dos    db    'IDrv: Not PC DOS ',cr,lf,lf,'$'
  1023. help_scr    db    'usage: idrv [options] [d:\path\]filename.ext [parms]',cr,lf
  1024.         db    'options:',cr,lf
  1025.         db    ' -h = load high (in UMB)',cr,lf
  1026.         db    " -l = load low (default)",cr,lf
  1027.         db    cr,lf
  1028.         db    'If you find this program useful please send $10 to:',cr,lf
  1029.         db    '        Janusz Wojcik',cr,lf
  1030.         db    '        20-608 Lublin',cr,lf
  1031.         db    '        ul.Wajdeloty 6/13',cr,lf
  1032.         db    '        Poland',cr,lf
  1033. HELP_LEN    equ    $ - help_scr
  1034. inv_option    db    'IDrv: invalid option! ',cr,lf,lf,'$'
  1035. header        db    'Device Drivers Installer  v1.06',cr,lf
  1036.         db    '(C)  1990  by Janusz Wojcik Lublin,Poland.',cr,lf,lf,'$'
  1037. ;....................................................................................
  1038. LEN        equ    $ - new_seg
  1039.  
  1040. code        ENDS
  1041.         END    start
  1042.