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

  1. ;                        ----------------------------
  2. ;                        KBDHNDLR 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 KQSIZE = 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 KQ: QUEUE;     (* must be declared in outermost block *)
  18. ;
  19. ;        PROCEDURE KBDINIT (VAR Q: QUEUE; SIZE:INTEGER); EXTERNAL;
  20. ;        PROCEDURE KBDFINIT; EXTERNAL;
  21. ;
  22. ;        KBDINIT (KQ,KQSIZE);    (* initialize the queue handler *)
  23. ;
  24. ;        WHILE TRUE DO
  25. ;          WITH KQ 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. ;        KBDFINIT;       (* 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 KBDFINIT, 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.  (KBDFINIT 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. KDB       .EQU   177562          ; Receive Data Buffer absolute address
  60. KSR       .EQU   177560          ; Receive Status Register absolute address
  61. KINTV     .EQU       60          ; 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  KBDINIT,2         ; (VAR Q:QUEUE, SIZE:INTEGER)
  67. ;
  68.           .DEF   KBDLOC          ; holds vector address
  69.           .DEF   KBDPR           ; holds old 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,KQADRS       ; 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. ;
  81.           MOV    @#KINTV,KBDLOC      ; save old interrupt vector
  82.           MOV    @#KINTV+2,KBDPR     ; and old priority
  83.  
  84.           MOV    #KHNDLR,@#KINTV     ; store interrupt handler address
  85.           MOV    #200,@#KINTV+2      ; set interrupt priority 4 for TTY input
  86.           ;MOV    #100,@#KSR          ; enable interrupts for TTY input
  87. ;
  88.           MOV    (SP)+,R0        ; pop return address from stack
  89.           ADD    #4,SP           ; discard 2 parameters (4 bytes)
  90.           JMP    @R0             ; and return to PASCAL interpreter
  91. ;
  92. KQADRS    .WORD   0              ; holds Q address for handler
  93. KBDLOC    .WORD   0              ; holds old interrupt vector
  94. KBDPR     .WORD   0              ; holds old interrupt priority
  95. ;
  96. QSIZE     .EQU    0              ; offset from Q
  97. INP       .EQU    2              ; likewise
  98. OUTP      .EQU    4
  99. MAXCHAR   .EQU    6
  100. DATA      .EQU   10
  101. ;
  102. KHNDLR:   MOV    R0,-(SP)        ; free registers R0, R1, R2 for use
  103.           MOV    R1,-(SP)
  104.           MOV    R2,-(SP)
  105.           MOV    KQADRS,R2       ; fetch Q address saved by KBDINIT
  106.           MOV    INP(R2),R0      ; fetch INP value
  107.           MOV    R0,R1           ; make a working copy
  108.           ADD    R2,R1           ; R1 = address (Q) + value (INP)
  109.           MOVB   @#KDB,DATA(R1)  ; DATA[INP] := input character
  110.           BICB   #200,DATA(R1)   ; clear bit 8 (parity)
  111.           BEQ    EXIT            ; ignore nulls (do not bump INP)
  112.           INC    R0              ; INP := INP+1
  113.           CMP    QSIZE(R2),R0
  114.           BPL    NOWRAP          ; if QSIZE >= INP then no wraparound
  115.           CLR    R0              ; else INP := 0
  116. NOWRAP    MOV    R0,INP(R2)      ; restore INP
  117. ;
  118.           SUB    OUTP(R2),R0
  119.           BMI    INOUT
  120.           BEQ    INOUT
  121.           BR     OUTIN           ; if INP > OUTP, # char = INP - OUTP
  122. INOUT     ADD    QSIZE(R2),R0    ; otherwise, # char = QSIZE+1 + INP - OUTP
  123.           ADD    #1,R0
  124. OUTIN     CMP    MAXCHAR(R2),R0
  125.           BPL    EXIT            ; if MAXCHAR >= # char, exit
  126.           MOV    R0,MAXCHAR(R2)  ; otherwise, store new MAXCHAR
  127. ;
  128. EXIT      MOV    (SP)+,R2        ; restore registers for caller
  129.           MOV    (SP)+,R1
  130.           MOV    (SP)+,R0
  131.           RTT                    ; return from interrupt
  132. ;
  133. CLKHNDLR: COM    CLKFLG          ; do not reexecute BPT if BPT handler
  134.           BEQ    CLKEXIT         ;   takes so long that clock ticks again
  135.           BPT                    ; let breakpoint transfer to old clock
  136. CLKEXIT   COM    CLKFLG          ; reset flag
  137.           RTI                    ; and exit
  138. ;
  139. CLKFLG    .WORD  0               ; flags reentry before BPT exit
  140. ;
  141.           .PROC  KBDFINIT
  142.           .REF   KBDLOC          ; old interrupt vector saved by KBDINIT
  143.           .REF   KBDPR           ; old kbd priority saved by KBDINIT
  144. ;
  145.            MOV    @#KBDPR,@#KINTV+2    ; restore interrupt priority
  146.            MOV    @#KBDLOC,@#KINTV     ; and interrupt vector
  147.            RTS    PC                   ; and return
  148. ;
  149.            .END
  150.  
  151.  
  152.