home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / m / msc7.zip / INTRRUPT.ASM < prev    next >
Assembly Source File  |  1992-02-14  |  13KB  |  668 lines

  1. ;;
  2. ;; (c) Copyright 1992, Qualitas, Inc. All Rights Reserved
  3. ;;
  4. ;; Interrupt dispatching for DPMI class library
  5.  
  6. ;; The basic idea is that there is an entry point for each interrupt
  7. ;; (real and protected), for up to 16 callbacks, and for the processor
  8. ;; exceptions.  The entry points transfer control to a dispatcher that
  9. ;; looks up the actual address of the handler in a table, and calls it
  10. ;; after switching to a local stack.   Stacks are allocated in a stack-like
  11. ;; manner, i.e., each entry to the dispatcher grabs a new stack, and
  12. ;; releases it upon exit.  Only when there are recursive entries to the
  13. ;; dispatcher (for any handler) does more than one stack come into play.
  14. ;;
  15.  
  16. nStacks        equ 6
  17. intStackSize     equ 512
  18.  
  19.     public C initDispatch
  20.     public C setDispatch
  21.     public C setXDispatch
  22.     public C setCBDispatch
  23.     public C callHandler
  24.     public C callXHandler
  25.  
  26. .286p
  27. .model    small, C
  28.  
  29. .data
  30. ;;
  31. ;; The dispatch tables hold the address of the actual handler
  32. ;;
  33. interruptDispatchTable         label     word
  34.     realDispatchTable    dw    256 dup (?)
  35.     protDispatchTable    dw    256 dup (?)
  36.     callBackDispatchTable    dw    16 dup (?)
  37.     exceptionDispatchTable    dw    16 dup (?)
  38.  
  39. interruptStacks        db Nstacks*intStackSize dup (?)
  40. currentStack        dw 0
  41. realCS            dw ?
  42.  
  43. .code
  44. dataSel        dw    0        ;; selector for DGROUP
  45. codeAlias    dw    0        ;; data alias of code segment
  46. realDS        dw    0        ;; real paragraph of DGROUP
  47.  
  48. reg    UNION
  49.     l    dd    ?
  50.     s    dw    ?
  51. reg    ENDS
  52.  
  53. dpmiRegs_t STRUC            ;; the dpmi register structure
  54.     rEDI    reg        <>
  55.     rESI    reg        <>
  56.     rEBP    reg        <>
  57.     rRES    reg        <>
  58.     rEBX    reg        <>
  59.     rEDX    reg        <>
  60.     rECX    reg        <>
  61.     rEAX    reg        <>
  62.     rFlags  DW        ?
  63.     rES    DW        ?
  64.     rDS    DW        ?
  65.     rFS    DW        ?
  66.     rGS    DW        ?
  67.     rIP    DW        ?
  68.     rCS    DW        ?
  69.     rSP    DW        ?
  70.     rSS    DW        ?
  71. dpmiRegs_t ENDS
  72.  
  73.  
  74. excFrame        STRUC           ;; 16-bit DPMI exception frame
  75.     excErr     DW        ?
  76.     excIP    DW        ?
  77.     excCS    DW        ?
  78.     excFlags DW        ?
  79.     excSP    DW        ?
  80.     excSS    DW        ?
  81. excFrame        ENDS
  82.  
  83.  
  84. iFrame    STRUC            ;; frame pushed by dispatcher (pusha ...)
  85.     iFes    dw    ?
  86.     iFds    dw    ?
  87.     iFdi    dw     ?
  88.     iFsi    dw    ?
  89.     iFbp    dw    ?
  90.     iFxx    dw    ?
  91.     iFbx    dw    ?
  92.     iFdx    dw    ?
  93.     iFcx    dw    ?
  94.     iFax    dw    ?
  95.     iFnret    dw    ?
  96.     iFip    dw    ?
  97.     iFcs    dw    ?
  98.     iFflags    dw    ?
  99. iFrame    ENDS
  100.  
  101. ;;
  102. ;; The entry tables hold the code invoked by the DPMI host when a
  103. ;; handled event occurs.  Each entry calls the appropriate dispatcher,
  104. ;; pushing an identifying return address as it calls.
  105. ;;
  106. interruptEntryTable    label    near
  107.     realEntryTable    label    near
  108.     REPT 256
  109.         call dispatchIntr
  110.         nop
  111.     ENDM
  112.     protEntryTable    label    near
  113.     REPT 256
  114.         call dispatchIntr
  115.         nop
  116.     ENDM
  117.  
  118. callBackEntryTable label near
  119.     REPT 16
  120.         call dispatchCallBack
  121.         nop
  122.     ENDM
  123. exceptionEntryTable label near
  124.     REPT 16
  125.         call dispatchException
  126.         nop
  127.     ENDM
  128.  
  129. ;;
  130. ;; set up local information needed for dispatch
  131. ;;
  132. initDispatch    PROC  C
  133.     mov    ax, 0ah            ;; get data alias for code segment
  134.     mov    bx, cs
  135.     int    31h
  136.     mov    es, ax
  137.     mov    es:[codeAlias], ax
  138.     mov    es:[dataSel], ds
  139.  
  140.     mov    ax, 6            ;; get base of data segment
  141.     mov    bx, ds
  142.     int    31h
  143.     shr    dx, 4
  144.     shl    cx, 12
  145.     or    dx, cx
  146.     mov    es:[realDS], dx
  147.  
  148.     mov    ax, 6            ;; get base of code segment
  149.     mov    bx, cs
  150.     int    31h
  151.     shr    dx, 4
  152.     shl    cx, 12
  153.     or    dx, cx
  154.     mov    realCS, dx
  155.  
  156.     ret
  157. initDispatch    ENDP    
  158.  
  159. ;; The SetDispatch routines (setDispatch, setCBDispatch, and setXDispatch)
  160. ;; take as arguments the ordinal identifier (e.g. exception number), and the
  161. ;; address of the desired handler.  They return the far ptr that serves
  162. ;; as the vector to be passed to the DPMI host (this vector points into one
  163. ;; of the entry tables.  The handler address is stored in a dispatch table.
  164. ;;
  165. ;; setDispatch and setXDispatch write back the previous dispatch table
  166. ;; contents so that chained handlers can be successfully called through
  167. ;; the dispatch mechanism.
  168. ;;
  169. setDispatch    PROC C USES SI, intNum:WORD, vector:PTR, RorP:word, pDisp:PTR
  170.     xor    bx, bx
  171.     mov    bl, byte ptr intNum
  172.     cmp    RorP, 0
  173.     jz    skipAdd
  174.     add    bx, 256
  175. skipAdd:
  176.     shl    bx, 1
  177.  
  178.     mov    ax, vector
  179.     mov    si, pDisp
  180.     mov    cx, interruptDispatchTable[bx]
  181.     mov    [si], cx
  182.     mov    word ptr interruptDispatchTable[bx], ax
  183.     
  184.     shl    bx, 1
  185.     mov    ax, offset interruptEntryTable
  186.     add    ax, bx
  187.  
  188.     cmp    RorP, 0
  189.     jz    retRealCS
  190.  
  191.     mov    dx, cs
  192.     ret
  193.  
  194. retRealCS:
  195.     mov    dx, realCS
  196.     ret
  197. setDispatch    ENDP
  198.  
  199. ;; set call-back dispatch
  200. ;;
  201. setCBDispatch    PROC C cbNumber:WORD, vector:PTR
  202.     xor    bx, bx
  203.     mov    bl, byte ptr cbNumber
  204.     shl    bx, 1
  205.  
  206.     mov    ax, vector
  207.     mov    word ptr callBackDispatchTable[bx], ax
  208.     
  209.     shl    bx, 1
  210.     mov    ax, offset callBackEntryTable
  211.     add    ax, bx
  212.  
  213.     mov    dx, cs
  214.     ret
  215. setCBDispatch    ENDP
  216.  
  217. ;; set exception dispatch
  218. ;;
  219. setXDispatch    PROC C USES SI, xNumber:WORD, vector:PTR, prevDisp:PTR
  220.     xor    bx, bx
  221.     mov    bl, byte ptr xNumber
  222.     shl    bx, 1
  223.  
  224.     mov    ax, vector
  225.     mov    si, prevDisp
  226.     mov    cx, word ptr exceptionDispatchTable[bx]
  227.     mov    [si], cx
  228.     mov    word ptr exceptionDispatchTable[bx], ax
  229.     
  230.     shl    bx, 1
  231.     mov    ax, offset exceptionEntryTable
  232.     add    ax, bx
  233.  
  234.     mov    dx, cs
  235.     ret
  236. setXDispatch    ENDP
  237.  
  238. ;;
  239. ;; Dispatch interrupt
  240. ;;
  241. ;; This routine dispatches real and protected mode interrupts (i.e. the
  242. ;; code executes in both modes).
  243. ;;
  244. dispatchIntr PROC near
  245.     pusha                ;; save state build iFrame
  246.     push    ds
  247.     push    es
  248.  
  249.     mov    bp, sp            
  250.     mov    ax, [bp].iFnret        ;; determine which DS to load
  251.     cmp    ax, offset protEntryTable
  252.     ja    loadProtDS
  253.  
  254.     mov    ds, cs:[realDS]        ;; use real DS
  255.     jmp    setupStack
  256.  
  257. loadProtDS:
  258.     mov    ds, cs:[dataSel]    ;; load ds with DGROUP
  259.  
  260. setupStack:
  261.     inc    currentStack        ;; allocate stack 
  262.      mov    ax, currentStack    
  263.  
  264.                     ;; calc new sp
  265.     mov    cx, intStackSize    ;;  = currentStack*intStackSize +
  266.     mul    cx            ;;    &interruptStacks
  267.     lea    bx, interruptStacks
  268.     add    bx, ax            ;; bx is new sp
  269.  
  270.     mov    ax, sp            ;; save this ss:sp in cx:ax
  271.     mov    cx, ss
  272.     mov    dx, ds            ;; switch stacks
  273.     mov    ss, dx
  274.     mov    sp, bx
  275.     push    cx            ;; save ss:sp
  276.     push    ax
  277.  
  278.     mov    bp, sp
  279.     les    di, [bp]        ;; es:di points to iFrame
  280.                     
  281.     push    es:[di].iFcs        ;; push a dpmiRegs_t onto stack
  282.     push    es:[di].iFip
  283.     push    0            ;; gs
  284.     push    0            ;; fs
  285.     push    es:[di].iFds
  286.     push    es:[di].iFes
  287.     push    es:[di].iFflags
  288.     push    0
  289.     push    es:[di].iFax
  290.     push    0
  291.     push    es:[di].iFcx
  292.     push    0
  293.     push    es:[di].iFdx
  294.     push    0
  295.     push    es:[di].iFbx
  296.     push    0
  297.     push    0
  298.     push    0
  299.     push    es:[di].iFbp
  300.     push    0
  301.     push    es:[di].iFsi
  302.     push    0
  303.     push    es:[di].iFdi
  304.  
  305.     mov    bx, es:[di].iFnret    ;; where are we coming from
  306.     sub    bx, offset interruptEntryTable+3
  307.     shr    bx, 1
  308.     call    interruptDispatchTable[bx]
  309.  
  310.     les    di, [bp]        ;; es:di points to iFrame
  311.     
  312.     pop    es:[di].iFdi        ;; pop dpmiRegs_t to original stack
  313.     pop    ax
  314.     pop    es:[di].iFsi
  315.     pop    ax
  316.     pop    es:[di].iFbp
  317.     pop    ax
  318.     pop    ax
  319.     pop    ax
  320.     pop    es:[di].iFbx
  321.     pop    ax
  322.     pop    es:[di].iFdx
  323.     pop    ax
  324.     pop    es:[di].iFcx
  325.     pop    ax
  326.     pop    es:[di].iFax
  327.     pop    ax
  328.     pop    es:[di].iFflags
  329.     pop    es:[di].iFes
  330.     pop    es:[di].iFds
  331.     pop    ax
  332.     pop    ax
  333.     pop    es:[di].iFip
  334.     pop    es:[di].iFcs
  335.  
  336.     push    es            ;; switch back to original stack
  337.     pop    ss    
  338.     mov    sp, di
  339.  
  340.     dec    currentStack
  341.     pop    es            ;; restore state and exit
  342.     pop    ds
  343.     popa
  344.     add    sp, 2
  345.     iret
  346. dispatchIntr ENDP
  347.  
  348. ;; Dispatch call-back
  349. ;;
  350. dispatchCallBack PROC C  
  351.     pusha                ;; save state - set up iFrame
  352.     push    ds
  353.     push    es
  354.  
  355.     mov    bp, sp
  356.     
  357.     mov    ax, ds:[si]
  358.     mov    es:[di].rIP, ax
  359.     mov    ax, ds:[si].2
  360.     mov    es:[di].rCS, ax 
  361.     add    es:[di].rSP, 4
  362.     
  363.     mov    ds, cs:[dataSel]    ;; load ds with DGROUP
  364.  
  365.     inc    currentStack
  366.      mov    ax, currentStack    ;; cycle stack sequence
  367.  
  368.                     ;; calc new sp
  369.     mov    cx, intStackSize    ;;  = currentStack*intStackSize +
  370.     mul    cx            ;;    &interruptStacks
  371.     lea    bx, interruptStacks
  372.     add    bx, ax            ;; bx is new sp
  373.  
  374.     mov    ax, sp            ;; save this ss:sp in cx:ax
  375.     mov    cx, ss
  376.     mov    dx, ds            ;; switch stacks
  377.     mov    ss, dx
  378.     mov    sp, bx
  379.     push    cx            ;; save ss:sp
  380.     push    ax
  381.  
  382.     mov    bp, sp
  383.     les    di, [bp]        ;; es:di points to iFrame
  384.  
  385.     mov    dx, es:[di].iFnret
  386.     sub    dx, offset callBackEntryTable+3
  387.     shr    dx, 1
  388.  
  389.     mov    si, es:[di].iFdi
  390.     mov    es, es:[di].iFes
  391.  
  392.     mov    cx, size dpmiRegs_t
  393.     mov    bx, cx
  394.     shr    cx, 1
  395. pushRegs:
  396.     sub    bx, 2
  397.     push    es:[si+bx]
  398.     loop    pushRegs
  399.  
  400.     mov    bx, dx
  401.     call    callBackDispatchTable[bx]    ;; call call back handler
  402.  
  403.     mov    ds, cs:[dataSel]
  404.     les    di, [bp]        ;; es:di points to iFrame
  405.  
  406.     mov    si, es:[di].iFdi    ;; es:si points to dpmiRegs_t
  407.     mov    es, es:[di].iFes
  408.  
  409.     mov    cx, size dpmiRegs_t/2
  410.     xor    bx, bx
  411. popRegs:
  412.     pop    es:[si+bx]
  413.     add    bx, 2
  414.     loop    popRegs
  415.  
  416.  
  417.     push    [bp+2]            ;; switch back to original stack
  418.     pop    ss    
  419.     mov    sp, di
  420.  
  421.     dec    currentStack
  422.     pop    es            ;; restore state and exit
  423.     pop    ds
  424.     popa
  425.     add    sp, 2
  426.     iret
  427. dispatchCallBack ENDP
  428.  
  429.  
  430. ;;
  431. ;; Dispatch exception
  432. ;;
  433. dispatchException PROC
  434.     pusha                ;; save state - setup iFrame
  435.     push    ds
  436.     push    es
  437.     mov    bp, sp
  438.  
  439.     mov    ds, cs:[dataSel]    ;; load ds with DGROUP
  440.  
  441.     inc    currentStack
  442.      mov    ax, currentStack    ;; cycle stack sequence
  443.                     ;; calc new sp
  444.     mov    cx, intStackSize    ;;  = currentStack*intStackSize +
  445.     mul    cx            ;;    &interruptStacks
  446.     lea    bx, interruptStacks
  447.     add    bx, ax            ;; bx is new sp
  448.  
  449.     mov    ax, sp            ;; save this ss:sp in cx:ax
  450.     mov    cx, ss
  451.     mov    dx, ds            ;; switch stacks
  452.     mov    ss, dx
  453.     mov    sp, bx
  454.     push    cx            ;; save ss:sp
  455.     push    ax
  456.  
  457.     mov    bp, sp
  458.     les    di, [bp]        ;; es:di points to iFrame
  459.  
  460.     mov    bx, es:[di].iFnret
  461.     sub    bx, offset exceptionEntryTable+3
  462.     shr    bx, 1
  463.     mov    dx, exceptionDispatchTable[bx]
  464.  
  465.     mov    bx, size iFrame+ size excFrame - 2
  466.     mov    cx, size excFrame
  467.     shr    cx, 1
  468.  
  469. pushXFrame:
  470.     sub    bx, 2
  471.     push    es:[di+bx]
  472.     loop    pushXFrame
  473.  
  474.                 ;; push dpmiRegs_t to reflect iFrame state
  475.     push    0        ;; SS:SP null
  476.     push    0
  477.     push    0        ;; CS:IP null
  478.     push    0
  479.     
  480.     push    0        ;; gs
  481.     push    0        ;; fs
  482.     push    es:[di].iFds
  483.     push    es:[di].iFes
  484.     push    0        ;; flags
  485.     push    0
  486.     push    es:[di].iFax
  487.     push    0
  488.     push    es:[di].iFcx
  489.     push    0
  490.     push    es:[di].iFdx
  491.     push    0
  492.     push    es:[di].iFbx
  493.     push    0
  494.     push    0
  495.     push    0
  496.     push    es:[di].iFbp
  497.     push    0
  498.     push    es:[di].iFsi
  499.     push    0
  500.     push    es:[di].iFdi
  501.  
  502.     push    offset continue
  503.     push    dx
  504.     retn
  505.  
  506. continue:
  507.     mov    bp, sp
  508.     add    bp, size excFrame + size dpmiRegs_t
  509.     les    di, [bp]        ;; es:di points to iFrame
  510.  
  511.     pop    es:[di].iFdi        ;; pop dpmiRegs_t to original stack
  512.     pop    ax
  513.     pop    es:[di].iFsi
  514.     pop    ax
  515.     pop    es:[di].iFbp
  516.     pop    ax
  517.     pop    ax
  518.     pop    ax
  519.     pop    es:[di].iFbx
  520.     pop    ax
  521.     pop    es:[di].iFdx
  522.     pop    ax
  523.     pop    es:[di].iFcx
  524.     pop    ax
  525.     pop    es:[di].iFax
  526.     pop    ax
  527.     pop    es:[di].iFflags
  528.     pop    es:[di].iFes
  529.     pop    es:[di].iFds
  530.     add    sp, 6*2
  531.  
  532.     mov    bx, size iFrame-2
  533.  
  534.     pop    es:[di+bx].excErr
  535.     pop    es:[di+bx].excIP
  536.     pop    es:[di+bx].excCS
  537.     pop    es:[di+bx].excFlags
  538.     pop    es:[di+bx].excSP
  539.     pop    es:[di+bx].excSS
  540.  
  541.     push    [bp+2]            ;; switch back to original stack
  542.     pop    ss    
  543.     mov    sp, di
  544.  
  545.     dec    currentStack
  546.     pop    es            ;; restore state and exit
  547.     pop    ds
  548.     popa
  549.     add    sp, 2
  550.     retf
  551. dispatchException ENDP
  552.  
  553.  
  554. ;;
  555. ;;  Call previous interrupt handler - used for both real and protected
  556. ;;  mode callPrevious members.
  557. ;;
  558. ;;  Restores the register state in pRegs, and passes control to the
  559. ;;  handler indicated by the handler argument
  560. ;;
  561. callHandler PROC C USES SI DI DS ES, pRegs:PTR, handler:FAR PTR
  562.     push    bp
  563.     pushf                    ; push fake iret frame
  564.     push    cs                ;   to regain control
  565.     push    offset cHret            ;   after invoking handler
  566.  
  567.     push    word ptr handler+2        ; push handler address
  568.     push    word ptr handler        ;   will retf to it
  569.  
  570.     mov    bx, pRegs            ; push regs state as if pusha
  571.     push    [bx].rDS
  572.     push    [bx].rES
  573.     push    [bx].rEAX.s
  574.     push    [bx].rECX.s
  575.     push    [bx].rEDX.s
  576.     push    [bx].rEBX.s
  577.     push    [bx].rRES.s
  578.     push    [bx].rEBP.s
  579.     push    [bx].rESI.s
  580.     push    [bx].rEDI.s
  581.  
  582.     popa                    ; restore register state
  583.     pop    es
  584.     pop    ds
  585.     retf                    ; call handler
  586.  
  587. cHret:                        ; handler returns here
  588.     pusha                    ; capture result state
  589.     push    ds
  590.     push    es
  591.  
  592.     mov    bp, sp                ; restore local frame
  593.     mov    bp, [bp+20]
  594.     mov    bx, pRegs
  595.     push    ss
  596.     pop    ds
  597.  
  598.     pop    [bx].rES            ; pop result state to 
  599.     pop    [bx].rDS            ;   register structure
  600.     pop    [bx].rEDI.s
  601.     pop    [bx].rESI.s
  602.     pop    [bx].rEBP.s
  603.     pop    [bx].rRES.s
  604.     pop    [bx].rEBX.s
  605.     pop    [bx].rEDX.s
  606.     pop    [bx].rECX.s
  607.     pop    [bx].rEAX.s
  608.  
  609.     pop    bp
  610.  
  611.     ret                
  612. callHandler ENDP
  613.  
  614. ;;
  615. ;; Call previous exception handler
  616. ;;
  617. callXHandler PROC C USES SI DI DS ES, dRegs:PTR, excFr:PTR, handler:FAR PTR
  618.     push    bp
  619.  
  620.     mov    bx, excFr
  621.     push    [bx].excSS            ;; push the exception frame
  622.     push    [bx].excSP
  623.     push    [bx].excFlags
  624.     push    [bx].excCS
  625.     push    [bx].excIP
  626.     push    [bx].excErr
  627.  
  628.     push    cs                ;; push fake retf frame to
  629.     push    offset cXHret            ;;   to regain control after
  630.                         ;;   invoking handler
  631.     push    word ptr handler+2        ;; push handler address
  632.     push    word ptr handler        ;;   will retf to it
  633.  
  634.     mov    bx, dRegs            ;; push reg state as if pusha
  635.     push    [bx].rDS
  636.     push    [bx].rES
  637.     push    [bx].rEAX.s
  638.     push    [bx].rECX.s
  639.     push    [bx].rEDX.s
  640.     push    [bx].rEBX.s
  641.     push    [bx].rRES.s
  642.     push    [bx].rEBP.s
  643.     push    [bx].rESI.s
  644.     push    [bx].rEDI.s
  645.  
  646.     popa                    ;; restore register state
  647.     pop    es
  648.     pop    ds
  649.     retf                    ;; call handler
  650.  
  651. cXHret:
  652.     mov    bp, sp
  653.     mov    bp, [bp+size excFrame]        ;; restore bp
  654.     mov    bx, excFr
  655.     pop    [bx].excErr            ;; pop any frame changes by
  656.     pop    [bx].excIP            ;;   previous handler
  657.     pop    [bx].excCS
  658.     pop    [bx].excFlags
  659.     pop    [bx].excSP
  660.     pop    [bx].excSS
  661.  
  662.     pop    bp
  663.  
  664.     ret
  665. callXHandler ENDP
  666.  
  667.     end
  668.