home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ucsdterak.zip / rcvhandlr.text < prev    next >
Text File  |  1984-04-11  |  7KB  |  157 lines

  1. ;                        ----------------------------
  2. ;                        RCVHNDLR TTY Receive Handler
  3. ;                        ----------------------------
  4. ;
  5. ;    Two routines are provided that maintain an interrupt-driven
  6. ;    TTY-receive queue.  Appropriate PASCAL declarations are:
  7. ;
  8. ;        CONST RCVQSIZE = maximum number of queued characters
  9. ;
  10. ;        TYPE QUEUE = RECORD    (* These are order-dependent !!! *)
  11. ;                       QSIZE: INTEGER;
  12. ;                       INP: INTEGER;
  13. ;                       OUTP: INTEGER;
  14. ;                       MAXCHAR: INTEGER;
  15. ;                       DATA: PACKED ARRAY [0..RCVQSIZE] OF CHAR;
  16. ;                     END;
  17. ;        VAR RCVQ: QUEUE;     (* must be declared in outermost block *)
  18. ;
  19. ;        PROCEDURE RCVINIT (VAR Q: QUEUE; SIZE:INTEGER); EXTERNAL;
  20. ;        PROCEDURE RCVFINIT; EXTERNAL;
  21. ;
  22. ;        RCVINIT (RCVQ,RCVQSIZE);    (* initialize the queue handler *)
  23. ;
  24. ;        WHILE TRUE DO
  25. ;          WITH RCVQ DO
  26. ;           IF INP <> OUTP THEN    (* characters available *)
  27. ;             BEGIN
  28. ;               CH := DATA[OUTP];
  29. ;               OUTP := OUTP+1; IF OUTP > QSIZE THEN OUTP := 0;
  30. ;                ...
  31. ;             END;
  32. ;
  33. ;        RCVFINIT;       (* terminate the queue handler *)
  34. ;
  35. ;    The RECORD declaration for the queue must appear exactly as it
  36. ;    does above except that you can of course use any names you like.
  37. ;    Do NOT attempt to lump the first four integer variables together
  38. ;    into a single group of the form list:INTEGER.  In that case,
  39. ;    the compiler allocates them in reverse order, so that your code
  40. ;    and the interrupt handler will not agree about which words have
  41. ;    what meaning.
  42. ;
  43. ;    The queue handler runs continuously as an interrupt-driven task
  44. ;    at high priority.  As characters come in, it advances the queue
  45. ;    INP pointer and keeps track of the maximum number of characters in
  46. ;    the queue in the MAXCHAR variable.  Queue overflow is indicated
  47. ;    by MAXCHAR > QSIZE.  You must terminate by calling RCVFINIT, or
  48. ;    the TTY receive interrupts will be left enabled and you will end
  49. ;    up crashing the system by executing garbage code when the next
  50. ;    character is received.  (RCVFINIT also repairs the interrupt
  51. ;    vectors for breakpoints and the clock, so failing to call it will
  52. ;    quite likely crash the system even in the absence of incoming
  53. ;    TTY characters.)
  54. ;
  55. ;    The manipulation of the clock and BPT interrupt vectors is borrowed
  56. ;    from UCSD's old communications program.  The purpose is to allow
  57. ;    the clock handler to be interrupted by incoming TTY characters.
  58. ;
  59. RDB       .EQU   177522          ; Receive Data Buffer absolute address
  60. RSR       .EQU   177520          ; Receive Status Register absolute address
  61. RCVINTV   .EQU      120          ; Receiver Interrupt Vector address
  62. CLKINTV   .EQU      100          ; Clock interrupt vector address
  63. BPTINTV   .EQU       14          ; BPT interrupt vector address
  64. QXCINTV   .EQU      250          ; QX controller interrupt vector
  65. ;
  66.           .PROC  RCVINIT,2       ; (VAR Q:QUEUE, SIZE:INTEGER)
  67. ;
  68.           .DEF   BPTLOC          ; used to save BPT interrupt handler adrs
  69.           .DEF   BPTPR           ; used to save BPT handler priority
  70. Q         .EQU   4               ; stack offset for Q address
  71. SIZE      .EQU   2               ; stack offset for QSIZE value
  72. ;
  73.           MOV    Q(SP),R0        ; obtain the Q record address
  74.           MOV    R0,RCVQADRS     ; remember Q address
  75.           MOV    SIZE(SP),(R0)+  ; store size in QSIZE word
  76.           MOV    #0,(R0)+        ; clear INP, OUTP, and MAXCHAR
  77.           MOV    #0,(R0)+
  78.           MOV    #0,(R0)
  79. ;
  80.           MOV    @#BPTINTV,BPTLOC    ; save old BPT handler address
  81.           MOV    @#BPTINTV+2,BPTPR   ; and old BPT handler priority
  82.           MOV    @#CLKINTV,@#BPTINTV ; make BPT vector point to old clock
  83.           MOV    #0,@#BPTINTV+2      ; and let it run at low priority
  84.           MOV    #CLKHNDLR,@#CLKINTV ; and replace clock handler with ours
  85.           MOV    #0,@#QXCINTV+2      ; make floppy interruptable
  86. ;
  87.           MOV    #RCVHNDLR,@#RCVINTV ; store interrupt handler address
  88.           MOV    #200,@#RCVINTV+2    ; set interrupt priority 4 for TTY input
  89.           MOV    #100,@#RSR          ; enable interrupts for TTY input
  90. ;
  91.           MOV    (SP)+,R0        ; pop return address from stack
  92.           ADD    #4,SP           ; discard 2 parameters (4 bytes)
  93.           JMP    @R0             ; and return to PASCAL interpreter
  94. ;
  95. RCVQADRS  .WORD   0              ; holds Q address for handler
  96. BPTLOC    .WORD   0              ; saves old BPT handler location
  97. BPTPR     .WORD   0              ; saves old BPT handler priority
  98. ;
  99. QSIZE     .EQU    0              ; offset from Q
  100. INP       .EQU    2              ; likewise
  101. OUTP      .EQU    4
  102. MAXCHAR   .EQU    6
  103. DATA      .EQU   10
  104. ;
  105. RCVHNDLR: MOV    R0,-(SP)        ; free registers R0, R1, R2 for use
  106.           MOV    R1,-(SP)
  107.           MOV    R2,-(SP)
  108.           MOV    RCVQADRS,R2     ; fetch Q address saved by RCVINIT
  109.           MOV    INP(R2),R0      ; fetch INP value
  110.           MOV    R0,R1           ; make a working copy
  111.           ADD    R2,R1           ; R1 = address (Q) + value (INP)
  112.           MOVB   @#RDB,DATA(R1)  ; DATA[INP] := input character
  113.           BICB   #200,DATA(R1)   ; clear bit 8 (parity)
  114.           BEQ    EXIT            ; ignore nulls (do not bump INP)
  115.           INC    R0              ; INP := INP+1
  116.           CMP    QSIZE(R2),R0
  117.           BPL    NOWRAP          ; if QSIZE >= INP then no wraparound
  118.           CLR    R0              ; else INP := 0
  119. NOWRAP    MOV    R0,INP(R2)      ; restore INP
  120. ;
  121.           SUB    OUTP(R2),R0
  122.           BMI    INOUT
  123.           BEQ    INOUT
  124.           BR     OUTIN           ; if INP > OUTP, # char = INP - OUTP
  125. INOUT     ADD    QSIZE(R2),R0    ; otherwise, # char = QSIZE+1 + INP - OUTP
  126.           ADD    #1,R0
  127. OUTIN     CMP    MAXCHAR(R2),R0
  128.           BPL    EXIT            ; if MAXCHAR >= # char, exit
  129.           MOV    R0,MAXCHAR(R2)  ; otherwise, store new MAXCHAR
  130. ;
  131. EXIT      MOV    (SP)+,R2        ; restore registers for caller
  132.           MOV    (SP)+,R1
  133.           MOV    (SP)+,R0
  134.           RTT                    ; return from interrupt
  135. ;
  136. CLKHNDLR: COM    CLKFLG          ; do not reexecute BPT if BPT handler
  137.           BEQ    CLKEXIT         ;   takes so long that clock ticks again
  138.           BPT                    ; let breakpoint transfer to old clock
  139. CLKEXIT   COM    CLKFLG          ; reset flag
  140.           RTI                    ; and exit
  141. ;
  142. CLKFLG    .WORD  0               ; flags reentry before BPT exit
  143. ;
  144.           .PROC  RCVFINIT
  145.           .REF   BPTLOC          ; old BPT handler loc, saved by RCVINIT
  146.           .REF   BPTPR           ; old BPT handler priority, likewise
  147. ;
  148.           MOV    #0,@#RSR             ; disable receive interrupt
  149.           MOV    @#BPTINTV,@#CLKINTV  ; repair clock interrupt vector
  150.           MOV    @#BPTPR,@#BPTINTV+2  ; reestablish BPT handler priority
  151.           MOV    @#BPTLOC,@#BPTINTV   ; repair BPT handler address
  152.           MOV    #340,@#QXCINTV+2     ; repair QX controller vector
  153.           RTS    PC                   ; and return
  154. ;
  155.           .END
  156.  
  157.