home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 9 / 09.iso / e / e065 / 2.ddi / UIO_386.ASM < prev    next >
Encoding:
Assembly Source File  |  1991-08-28  |  17.3 KB  |  606 lines

  1.         page    ,132
  2.         title   User I/O Assembly Language Interface Functions
  3.  
  4.         .286P
  5.  
  6. ; 16-Jan-91 cck
  7. ;    Modified to set/restore PSP for proper handling of dynamic memory.
  8. ; 29-Nov-89 cck
  9. ;       Kludge to overcome idiosyncracies of MSDOS 4.01
  10. ; 30-Sep-89 cck
  11. ;    Modified to release all memory blocks belonging to PSP
  12. ;************************************************************************
  13. ;*                                    *
  14. ;*    User I/O Assembly Code Interface: Defines            *
  15. ;*                                    *
  16. ;************************************************************************
  17. ;
  18. ;    *** WARNING *** WARNING *** WARNING ***
  19. ;       This program will ONLY work with DOS 3.0 and above
  20. ;    *** WARNING *** WARNING *** WARNING ***
  21. ;
  22. ;  Communication Structure:
  23. ;    Call:
  24. ;    AH    = register set to use:
  25. ;             0 = execute a NeuralWorks command
  26. ;             1 = return from User I/O request
  27. ;    AL    = request code (AH=0)
  28. ;
  29. ;    Return:
  30. ;    AL    = return code
  31. ;             0 = all is well
  32. ;             1 = refresh display
  33. ;            -1 = error / eof (AH = 0)
  34. ;
  35. ;        also placed in Data_transfer_ptr->RPC_area.request
  36. ;            refer to uio_if_d.c          
  37.  
  38. OpSize          MACRO
  39. ;        db      66h
  40.                 ENDM
  41.  
  42.  
  43. AdSize          MACRO
  44.                 db      67h
  45.                 ENDM
  46.  
  47. ;************************************************************************
  48. ;*                                    *
  49. ;*    Public Routine Declarations                    *
  50. ;*                                    *
  51. ;************************************************************************
  52.  
  53.         public  FindMem
  54.         public  _FindMem
  55.         public  _LeaveTSR
  56.  
  57.         public  _InitIO     ; initialize i/o interface
  58.         public  InitIO
  59.         public  _XUIF
  60.  
  61.  
  62. ;************************************************************************
  63. ;*                                    *
  64. ;*    Public Data Declarations                    *
  65. ;*                                    *
  66. ;************************************************************************
  67.  
  68. DGROUP        group    _DATA
  69.         assume    ds:DGROUP
  70. _DATA        segment word public 'DATA'
  71.  
  72.         public    __okbigbuf    ; for DataLight "C"
  73.         public    _IOStr,_IOData,_IOReqC,_IORtnC,_UserIOP
  74.         public    _IOCount,_IOLayer
  75.         public    _IOUIFC        ; user interface code
  76.         public    _IOPSP,_IOPara    ; program size
  77.         public    _ProgSize
  78.         public    _PProgName    ; program name pointer
  79.         public    _ProgEnd    ; pointer to end of program
  80.  
  81.         public    IOStr,IOData,IOReqC,IORtnC,UserIOP
  82.         public    IOCount,IOLayer
  83.         public    IOUIFC        ; user interface code
  84.         public    IOPSP,IOPara    ; program size
  85.         public    ProgSize
  86.         public    PProgName    ; program name pointer
  87.         public    ProgEnd        ; pointer to end of program
  88.  
  89. __okbigbuf    dw    0        ; special for DataLight "C" 
  90. IOStr        label    word
  91. _IOStr        dd    0        ; i/o string pointer
  92. IOData        label    word
  93. _IOData        dd    0        ; i/o data pointer
  94. IOCount        label    word
  95. _IOCount    dw    0        ; i/o # of data items
  96. IOLayer        label    word
  97. _IOLayer    dw    0        ; i/o layer number of request
  98. IOReqC        label    word
  99. _IOReqC        dw    0        ; i/o request code
  100. IORtnC        label    word
  101. _IORtnC        dw    0        ; i/o return  code
  102. IOUIFC        label    word
  103. _IOUIFC        dw    0        ; i/o user interface code
  104. ProgSize    label    word
  105. _ProgSize    dw    0        ; program size in paragraphs
  106. UserIOP        label    dword
  107. _UserIOP    dd    0        ; user i/o routine pointer
  108. IOPara        label    word
  109. _IOPara        dw    0        ; program size in paragraphs
  110. IOPSP        label    word
  111. _IOPSP        dw    0        ; program segment prefix (segment)
  112.  
  113. ProgEnd        label    dword        ; pointer to end of program
  114. _ProgEnd    dd    0
  115. PProgName    label    dword
  116. _PProgName    dd    0        ; pointer to program name
  117. ProgHandle    dw    0        ; program file handle
  118. DosHdr        label    word
  119.         dw    0        ; n/c: 4D5A
  120.         dw    0        ; n/c: bytes in last page
  121. ExeBlocks    dw    0        ; # of 512 byte blocks in image
  122.         dw    0        ; n/c: # of relocation entries
  123.         dw    0        ; n/c: size of header in paragraphs
  124. ExeMinAlc    dw    0        ; minimum # of paragraphs to allocate
  125. ExeMaxAlc    dw    0        ; maximum # of paragraphs to allocate
  126. DosHEnd        dw    0        ; End of Dos Header
  127. DosHLen        equ    DosHEnd-DosHdr    ; size of header to read
  128. _DATA        ends
  129.  
  130. ;************************************************************************
  131. ;*                                    *
  132. ;*    User I/O Assembly Code Interface                *
  133. ;*                                    *
  134. ;************************************************************************
  135.  
  136. USERUTL_PROG    segment    word 'CODE'
  137.         assume    cs:USERUTL_PROG
  138.  
  139. ;    *** Host Save Area ***
  140. ;
  141. ;    NOTE: though it is usually considered poor programming practice,
  142. ;    we are saving register data in the code segment because that is
  143. ;    the only thing we are always sure of.
  144. ;
  145. ;    The save area is broken into two parts.  The "main" part is used
  146. ;    to save register data when the program was initialized and thus
  147. ;    to invoke the user's i/o routine.
  148. ;
  149. ;    The "slave" part is used to save context information for
  150. ;    handling User I/O requests for information from NeuralWorks.
  151. ;    This allows NWORKS to do a return to the requesting function.
  152. ;
  153. PSP        dw    0        ; program segment prefix
  154. CALLPSP        dw    0        ; calling program PSP
  155. ParaLen        dw    0        ; length to save in paragraphs
  156.  
  157. SMS        dw    12 DUP (0)    ; slave save area
  158.  
  159. SAS        dw    12 DUP (0)    ; slave alternate save area
  160.  
  161. MyReqC        dw    0        ; my request code
  162.  
  163. _OldVec     dw  0,0     ; old vector
  164. MySvcRtne    dd    0        ; "my" service routine
  165. StrPtr        dd    _IOStr        ; point to the string pointer
  166. DataPtr        dd    _IOData        ; point to the data pointer
  167. DataSeg        dw    seg DGROUP    ; point to data segment
  168. Inited        db    0        ; see if we are initialized
  169. MyVecNum    db    0        ; interrupt used for communication
  170. MyVec           dd      InterruptH      ; new interrupt handling vector
  171.  
  172. MyBlock        dw    0,0,0,0,0,0    ; my "blocks" to free regardless
  173. MYBLOCKSIZE    equ    10        ; size of "blocks"
  174.  
  175. ;************************************************************************
  176. ;*                                    *
  177. ;*    Initiate The Interface with NWORKS                *
  178. ;*                                    *
  179. ;************************************************************************
  180.  
  181. VecNum  equ     word ptr ss:4[bp]
  182. SvcRtne equ     dword ptr ss:6[bp]
  183.  
  184. InitIO      proc    far
  185.         jmp far ptr _InitIO
  186. InitIO      endp
  187.  
  188. _InitIO proc    far
  189.         mov     SMS+0,  ax  ; save main's registers
  190.         mov     SMS+2,  bx
  191.         mov     SMS+4,  cx
  192.         mov     SMS+6,  dx
  193.         mov     SMS+8,  si
  194.         mov     SMS+10, di
  195.         mov     SMS+12, bp
  196.         mov     SMS+14, es
  197.         mov     SMS+16, ds
  198.         mov     SMS+18, ss
  199.         mov     SMS+20, sp
  200.         mov     bp, sp
  201.  
  202.         les     si, SvcRtne             ; get address of service routine
  203.         mov     word ptr MySvcRtne+0, si         ; save this for posterity
  204.         mov     word ptr MySvcRtne+2, es
  205.  
  206.         mov     ax, VecNum              ; get interrupt vector number
  207.         mov     MyVecNum, al
  208.  
  209. LSvcOK:
  210.     mov    ds, DataSeg        ; make sure we have right data segment
  211.  
  212.     mov    bx, _IOPSP        ; see if PSP was properly specified
  213.     or    bx, bx
  214.     jne    PSPOk
  215.     mov    ax, 05100h        ; get PSP
  216.     int    21h
  217. PSPOk:    mov    PSP, bx            ; save PSP for posterity
  218.     mov    ds, DataSeg        ; make sure we have right data segment
  219.     mov    _IOPSP, bx
  220.  
  221. ;  The program end has been specified, figure out whether the stack or
  222. ;  the heap are at the end and use that.
  223.  
  224.         mov    ax, word ptr _ProgEnd+0        ; cvt to paragraph
  225.         add    ax, 17                ; length 2 + round up
  226.         mov    cx, 4                ; position right
  227.         shr    ax, cl
  228.         and    ax, 0fffh            ; clean it up
  229.         add    ax, word ptr _ProgEnd+2        ; add in base seg
  230.         mov    bx, ax                ; save it (bx)
  231.  
  232.         push    ss                ; push stack seg
  233.         mov    ax, sp                ; get SP
  234.         add    ax, 127                ; round up
  235.         shr    ax, cl                ; cvt to paragraph
  236.         and    ax, 0fffh            ; clean it up
  237.         pop    cx                ; ss->cx
  238.         add    ax, cx                ; ax = end para for stk
  239.         cmp    ax, bx
  240.         jae    UseAX
  241.         mov    ax, bx
  242. UseAX:        sub    ax, _IOPSP            ; subtract off base
  243.         inc    ax                ; de-zero bias it
  244.  
  245.         mov    ParaLen, ax    ; save it for later
  246.         mov    _ProgSize, ax    ; and make it global
  247.  
  248. ; With the preliminaries done, attach to the interface vector.
  249. ; Save the existing vector first so that we can restore it later.
  250.  
  251. SetVector:
  252.  
  253. ; Find which memory belongs to this TSR for DOS4.01
  254.  
  255.         push    ds
  256.                 call    far ptr FindMem
  257.         pop    ds
  258.  
  259. ; Flag that we are initialized successfully, and do a terminate and 
  260. ; stay resident.
  261. ;
  262. ; NOTE: Unfortunately, terminate and stay resident CLOSES all open
  263. ; file handles.  Thus, it is necessary to open these file handles AFTER
  264. ; the main routine is DONE.
  265.  
  266.                 mov     Inited, -1      ; we are initialized
  267.  
  268.                 mov     al, MyVecNum    ; save the old user_vect server
  269.                 mov     ah, 35h
  270.                 int     21h
  271.                 mov     _OldVec+2, es
  272.                 mov     _OldVec+0, bx
  273.  
  274.                 lds     dx, MyVec       ; install the new user_vect server
  275.                 mov     al, MyVecNum
  276.                 mov     ah, 25h
  277.                 int     21h
  278.  
  279.                 mov     ah, 31h         ; terminate and stay resident
  280.         mov    dx, ParaLen    ; leave everything resident
  281.         int    21h
  282.  
  283. InitErr:                ; initialization error, die
  284.         mov    ax, 4cffh    ; terminate w/-1 code
  285.         int    21h
  286.  
  287. _InitIO         endp
  288.  
  289.  
  290. ;************************************************************************
  291. ;*                                    *
  292. ;*    Free all memory related to this program                *
  293. ;*                                    *
  294. ;************************************************************************
  295. ; NOTE: the following defines are used to manipulate system memory block
  296. ;   headers.  This is basically very dangerous, but necessary.  Do not
  297. ;   change or alter these or the code which frees memory unless you really
  298. ;   understand what we are doing and know how all of these undocumented
  299. ;   system calls and memory configurations work.
  300. ;
  301. MFLAG    equ    byte ptr ES:0[BX]
  302. MOWNER    equ    word ptr ES:1[BX]
  303. MSIZE    equ    word ptr ES:3[BX]
  304.  
  305. ;************************************************************************
  306. ;*                                    *
  307. ;*    Find Memory which belongs to this TSR                *
  308. ;*                                    *
  309. ;************************************************************************
  310. ;
  311. ; NOTE: DOS4.01 changes the owner of the block to the calling program
  312. ; when certain system calls are made.  As a result, it is necesary to get
  313. ; a list of TSR blocks prior to allowing the user to do their thing.
  314.  
  315. _FindMem    proc    far
  316.             jmp     FindMem
  317. _FindMem    endp
  318.  
  319. FindMem     proc    far
  320.  
  321. ;    --- Find which memory blocks belong to me and record them ---
  322.  
  323.     mov    ax,5200h    ; get pointer to DOS tables
  324.     int    21h        ; es:bx -> dos table, pick up -2
  325.     sub    bx, 2        ; bx[-2]
  326.     mov    ax, es:0[bx]    ; get paragraph number
  327.     xor    bx,bx        ; no offset
  328.     mov    es, ax        ; point to head of first memory block
  329.                 ; ex:bx points to first memory control block
  330.  
  331. ;    --- Search for & Release all Memory owned by this PSP ---
  332.  
  333.     mov    si, 0        ; index into my array
  334.     mov    dx, PSP        ; owner we are looking for
  335.     or    dx, dx        ; see if bad PSP
  336.     je    FindDone    ; PSP was never properly set.
  337. FindLoop:
  338.     mov    ax, MOWNER    ; paragraph owner
  339.     cmp    ax, dx
  340.     jne    FindNxtBlk    ; not ours, try next one
  341.  
  342.     mov    ax, es        ; point to memory block
  343.     inc    ax
  344.     mov    MyBlock[si], ax    ; save it
  345.     add    si, 2        ; next location
  346.     cmp    si, MYBLOCKSIZE    ; done?
  347.     jae    FindDone    ; yes, all spaces used
  348.  
  349. FindNxtBlk:
  350.     mov    al, MFLAG    ;pick up flag
  351.     cmp    al, 04dh    ;see if end if chain?
  352.     jne    FindDone    ;yes, go home
  353.  
  354.                 ;figure out next memory block by adding size +1
  355.     mov    ax, es        ;current segment
  356.     add    ax, MSIZE    ;add size of memory block
  357.     inc    ax        ;plus one for header
  358.     mov    es, ax        ; es:bx -> next memory block
  359.     jmp FindLoop        ; keep looking
  360.  
  361. FindDone:
  362.     ret
  363. FindMem    endp
  364.  
  365.  
  366. ;************************************************************************
  367. ;*                                    *
  368. ;*    Free Memory which belongs to this TSR                *
  369. ;*                                    *
  370. ;************************************************************************
  371.  
  372.         public  FreeMem
  373.         public  _FreeMem
  374.  
  375. _FreeMem proc   far
  376.         jmp     FreeMem
  377. _FreeMem endp
  378.  
  379. FreeMem proc    far
  380.  
  381. ;    --- Free memory which is Mine ---
  382.  
  383.     mov    si, 0        ; index into table
  384. MyFree:    mov    ax, MyBlock[si]    ; next block to free
  385.     or    ax, ax
  386.     je    MyFreeDone
  387.  
  388.     push    si
  389.     mov    es, ax
  390.     mov    ax, 4900h    ; deallocate program memory (es = para number)
  391.     int    21h
  392.     pop    si
  393.     add    si, 2
  394.     cmp    si, MYBLOCKSIZE
  395.     jb    MyFree
  396. MyFreeDone:
  397.  
  398. ;    --- Get pointer to the first of the Memory Control Blocks ---
  399.  
  400. ReFree:
  401.     mov    ax,5200h    ; get pointer to DOS tables
  402.     int    21h        ; es:bx -> dos table, pick up -2
  403.     sub    bx, 2        ; bx[-2]
  404.     mov    ax, es:0[bx]    ; get paragraph number
  405.     xor    bx,bx        ; no offset
  406.     mov    es, ax        ; point to head of first memory block
  407.                 ; ex:bx points to first memory control block
  408.  
  409. ;    --- Search for & Release all Memory owned by this PSP ---
  410.  
  411.     mov    dx, PSP        ; owner we are looking for
  412. FreeLoop:
  413.     mov    ax, MOWNER    ; paragraph owner
  414.     cmp    ax, dx
  415.     jne    NxtBlk        ; not ours, try next one
  416.  
  417.     push    es        ; save ES for next time through
  418.     mov    ax, es        ; point to memory block
  419.     inc    ax
  420.     mov    es, ax
  421.  
  422.     mov    ax, 4900h    ; deallocate program memory (es = para number)
  423.     int    21h
  424.     pop    es        ; restore last pointer
  425.     jmp    short ReFree    ; just to be safe!!
  426.  
  427. NxtBlk:
  428.     mov    al, MFLAG    ;pick up flag
  429.     cmp    al, 04dh    ;see if end if chain?
  430.     jne    FreeDone    ;yes, go home
  431.  
  432.                 ;figure out next memory block by adding size +1
  433.     mov    ax, es        ;current segment
  434.     add    ax, MSIZE    ;add size of memory block
  435.     inc    ax        ;plus one for header
  436.     mov    es, ax        ; es:bx -> next memory block
  437.     jmp    FreeLoop    ; keep looking
  438.  
  439. FreeDone:
  440.     ret
  441. FreeMem    endp
  442.  
  443. ;       Exit routine
  444. ;
  445.  
  446. _LeaveTSR   proc    far
  447.     mov    ds, _OldVec+2        ; load old handler
  448.     mov    dx, _OldVec+0
  449.     mov    al, MyVecNum        ; load interrupt number
  450.     mov    ah, 25h
  451.     int    21h
  452.     call    far ptr FreeMem
  453.     ret
  454. _LeaveTSR   endp
  455.  
  456.  
  457. HS              dw      26 DUP (0)      ; host save area
  458. HSAdr           dw      offset HS
  459.                 dw      seg HS
  460.  
  461. InterruptH      proc    far             ; interrupt from host
  462.                 cli
  463.                 OpSize
  464.                 mov     HS+0, ax
  465.                 OpSize
  466.                 mov     HS+4, bx
  467.                 OpSize
  468.                 mov     HS+8, cx
  469.                 OpSize
  470.                 mov     HS+12, dx
  471.                 OpSize
  472.                 mov     HS+16, si
  473.                 OpSize
  474.                 mov     HS+20, di
  475.                 OpSize
  476.                 mov     HS+24, bp
  477.                 OpSize
  478.                 mov     HS+28, sp
  479.  
  480.                 mov     HS+32, ss
  481.                 mov     HS+36, ds
  482.                 mov     HS+40, es
  483.         sti            ; turn interrupts back on for DOS
  484.  
  485.         push    ax        ; save "calling code"
  486. ;                    ---- get calling PSP & save it ---
  487.         mov    ax, 05100h    ; undocumented get psp
  488.         int    21h
  489.         mov    CALLPSP, bx    ; save calling PSP
  490. ;                    ---- set our PSP as current one ---
  491.         mov    bx, PSP
  492.         mov    ax, 05000h    ; undocumented set psp
  493.         int    21h
  494.  
  495.         pop    ax        ; restore "calling" code
  496.                 or      ah, ah          ; see if response to User I/O request
  497.                 je      HostInt         ; no, host command
  498.  
  499.                     ; restore calling registers
  500.                 mov     ax, SAS+18      ; set up return stack
  501.                 mov     bp, SAS+20
  502.                 cli
  503.                 mov     ss, ax
  504.                 mov     sp, bp
  505.                 sti
  506.                 mov     ax, SAS+0
  507.                 mov     bx, SAS+2
  508.                 mov     cx, SAS+4
  509.                 mov     dx, SAS+6
  510.                 mov     si, SAS+8
  511.                 mov     di, SAS+10
  512.                 mov     bp, SAS+12
  513.                 mov     es, SAS+14
  514.                 mov     ds, SAS+16
  515.                 ret                     ; return to caller
  516.  
  517. HostInt:                ; call the user service routine
  518.                 cli            ; turn interrupts off jc
  519.                 mov     ax, SMS+0       ; restore old context
  520.                 mov     bx, SMS+2
  521.                 mov     cx, SMS+4
  522.                 mov     dx, SMS+6
  523.                 mov     si, SMS+8
  524.                 mov     di, SMS+10
  525.                 mov     bp, SMS+12
  526.                 mov     es, SMS+14
  527.                 mov     ds, SMS+16
  528.                 mov     ss, SMS+18
  529.                 mov     sp, SMS+20
  530.  
  531.                 push    HSAdr+2
  532.                 push    HSAdr+0
  533.                 sti                     ; turn interrupts back on
  534.                 call    MySvcRtne
  535.  
  536. HostReturn:                             ; return to NWORKS
  537.         mov    bx, CALLPSP    ; --- restore calling PSP ---
  538.         mov    ax, 05000h    ; undocumented set psp
  539.         int    21h
  540.  
  541.                 cli                     ; turn interrupts off
  542.                 OpSize
  543.                 mov     ax, HS+0
  544.                 OpSize
  545.                 mov     bx, HS+4
  546.                 OpSize
  547.                 mov     cx, HS+8
  548.                 OpSize
  549.                 mov     dx, HS+12
  550.                 OpSize
  551.                 mov     si, HS+16
  552.                 OpSize
  553.                 mov     di, HS+20
  554.                 OpSize
  555.                 mov     bp, HS+24
  556.                 OpSize
  557.                 mov     sp, HS+28
  558.  
  559.                 mov     ss,  HS+32
  560.                 mov     ds,  HS+36
  561.                 mov     es,  HS+40
  562.                 iret
  563. InterruptH  endp
  564.  
  565. ;************************************************************************
  566. ;*                                    *
  567. ;*    XUIF - perform user i/o interface                *
  568. ;*                                    *
  569. ;************************************************************************
  570.  
  571. _XUIF        proc    far
  572.         push    ds
  573.         mov    ds, DataSeg
  574.         mov    ah, byte ptr _IOUIFC    ; get request code
  575.         pop    ds
  576. COM_IF:
  577.  
  578.         cmp    Inited, 0    ; see if we are ready
  579.         jne    SIO_OK        ; yes
  580.         ret            ; no, return immediately
  581. SIO_OK:
  582.         mov    SAS+0,  ax    ; save main's registers
  583.         mov    SAS+2,  bx
  584.         mov    SAS+4,  cx
  585.         mov    SAS+6,  dx
  586.         mov    SAS+8,  si
  587.         mov    SAS+10,    di
  588.         mov    SAS+12, bp
  589.         mov    SAS+14, es
  590.         mov    SAS+16, ds
  591.         mov    SAS+18, ss
  592.         mov    SAS+20, sp
  593.  
  594.         mov    ds, DataSeg        ; get data segment base
  595.  
  596.         xor    ax,ax            ; clear h.o. byte 
  597.         mov    al, byte ptr _IORtnC    ; user return code
  598.         mov    HS+0,  ax        ; save host return code
  599.  
  600.         jmp    HostReturn
  601. _XUIF        endp
  602.  
  603. USERUTL_PROG    ends
  604.  
  605.         end
  606.