mirror of
https://github.com/PDP-10/stacken.git
synced 2026-02-28 09:07:42 +00:00
1279 lines
36 KiB
Plaintext
1279 lines
36 KiB
Plaintext
TITLE TTYIO - Low level terminal routines and PSI control for AMIS.
|
||
SUBTTL Macros, definments and such things.
|
||
|
||
SEARCH UUOSYM,MACTEN ;Needed external symbols
|
||
SALL ;Listing control
|
||
|
||
TWOSEG 600000 ;Make this a two segment program
|
||
|
||
IFNDEF F$DBUG,<F$DBUG==0> ;Assume not debugging
|
||
IFNDEF F$KSYS,<F$KSYS==-1> ;Default for KSYS warnings
|
||
IFNDEF F$OPAR,<F$OPAR==-1> ;Default for output parity
|
||
IFNDEF F$META,<F$META==-1> ;Default for TERMINAL META TRMOP.
|
||
IFNDEF F$SUBT,<F$SUBT==-1> ;Default for TERMINAL SUBTYPE TRMOP.
|
||
|
||
IFNDEF BUFSIZ,<BUFSIZ==20> ;Default buffer size is 20 words
|
||
IFNDEF CCMAX,<CCMAX==3> ;Default is 3 ^C to break
|
||
IFNDEF MBFTIM,<MBFTIM==500> ;Default wakeup time (milliseconds)
|
||
IFNDEF PDLLEN,<PDLLEN==150> ;Default length of interrupt stack
|
||
IFNDEF TAHSIZ,<TAHSIZ==200> ;Default type ahead size (chars)
|
||
IFNDEF .TOMET,<.TOMET==1770> ;Local TRMOP., for TERMINAL [NO] META.
|
||
IFNDEF .TOSUB,<.TOSUB==1767> ;Local TRMOP., for TERMINAL SUBTYPE xxx.
|
||
IFNDEF .TOFLO,<.TOFLO==1764> ;Local TRMOP., for TERMINAL [NO] FLOWCONTROL.
|
||
|
||
METACH==200 ;The meta bit in a character
|
||
|
||
OPDEF CALL[ PUSHJ P,]
|
||
|
||
TTY==1 ;Channel to open TTY: on.
|
||
PTY==3 ;Channel to push to exec on.
|
||
|
||
STRSIZE==^D40 ;Length of strings.
|
||
|
||
T0==0
|
||
T1==1
|
||
T2==2
|
||
T3==3
|
||
T4==4
|
||
T5==5
|
||
T6==6
|
||
T7==7
|
||
P==17
|
||
SUBTTL BUG - Print bug message and exit to monitor
|
||
|
||
BUG:: SETZM RUNFIL## ;Really don't run anything after this...
|
||
PUSH P,T2 ;Save argument
|
||
MOVEI T2,[BYTE(7) "?",.CHCRT,.CHLFD,"?",.CHNUL]
|
||
CALL OUTSTR ;Print start of bug message
|
||
POP P,T7 ;Restore argument into T7
|
||
HRLI T7,(POINT 7) ;Make T7 a byte pointer to the string
|
||
MOVEI T3,STRSIZE ;Get length of string
|
||
BUG1: ILDB T2,T7 ;Get a character
|
||
JUMPE T2,BUG.2 ;If it's a <NUL>, break,
|
||
CALL TTYWRITE ; else print it
|
||
SOJG T3,BUG1 ; and loop back if more
|
||
BUG.2: CALL MONITOR ;Kick him out
|
||
MOVEI T2,[ASCIZ "Use the monitor command 'REENTER' to restart."]
|
||
CALL OUTSTR ;Print string
|
||
JRST BUG.2 ; and loop back to monitor
|
||
SUBTTL DAYTIME - Give back a string containing date and time
|
||
|
||
DAYTIM::CALL BLANKS ;Clear string
|
||
HRLI T2,(POINT 7) ;Make T2 a byte pointer to string
|
||
MOVE T0,[%CNYER]
|
||
GETTAB T0, ;Get current year
|
||
SETZ T0,
|
||
IDIVI T0,^D100 ;Divide into first and last digit pairs
|
||
PUSH P,T0+1 ;Save last two digits
|
||
CALL TWODIG ;Put first two in string
|
||
POP P,T0 ;Get last two digits again
|
||
CALL TWODIG ;Deposit them too
|
||
MOVEI T0,"-" ;Get a hyphen
|
||
IDPB T0,T2 ;Deposit it
|
||
MOVE T0,[%CNMON]
|
||
GETTAB T0, ;Get current month
|
||
SETZ T0,
|
||
CALL TWODIG ;Deposit them
|
||
MOVEI T0,"-" ;Get a hyphen
|
||
IDPB T0,T2 ;Deposit it
|
||
MOVE T0,[%CNDAY]
|
||
GETTAB T0, ;Get current day
|
||
SETZ T0,
|
||
CALL TWODIG ;Deposit day
|
||
MOVEI T0," " ;Get a space
|
||
IDPB T0,T2 ;Put it in string
|
||
MOVE T0,[%CNHOR]
|
||
GETTAB T0, ;Get current hour
|
||
SETZ T0,
|
||
CALL TWODIG ;Put hour in string
|
||
MOVEI T0,":" ;Get a colon
|
||
IDPB T0,T2 ;Put it into string
|
||
MOVE T0,[%CNMIN]
|
||
GETTAB T0, ;Get current minute
|
||
SETZ T0,
|
||
CALL TWODIG ;Put minutes into string
|
||
MOVEI T0,":" ;Get a colon again
|
||
IDPB T0,T2 ;Put it into string
|
||
MOVE T0,[%CNSEC]
|
||
GETTAB T0, ;Get current seconds
|
||
SETZ T0,
|
||
|
||
TWODIG: IDIVI T0,^D10 ;Divide argument into first and second
|
||
ADDI T0,"0" ; digits, then make them ascii chars.
|
||
ADDI T0+1,"0"
|
||
IDPB T0,T2 ;Deposit first...
|
||
IDPB T0+1,T2 ; then second digit into goal string
|
||
POPJ P,
|
||
SUBTTL GetVersion -- Get current version number, encode in string arg.
|
||
|
||
GETVER::PUSHJ P,BLANKS ;Blank out string.
|
||
HRLI T2,(POINT 7) ;Make a byte pointer.
|
||
SKIPA T3,[
|
||
POINT 7,[ ;1234567890123456789012345678901234567890
|
||
ASCIZ "Tops-10 AMIS, Version 1C, edit # "]]
|
||
GVER.2: IDPB T0,T2 ;Store in string.
|
||
ILDB T0,T3 ;Load next byte.
|
||
JUMPN T0,GVER.2 ;Loop until null.
|
||
HRRZ T3,.JBVER ;Get edit number.
|
||
IDIVI T3,^O100 ;Divide away first digit of three.
|
||
IDIVI T4,^O10 ;Split second and third digit.
|
||
MOVEI T3,"0"(T3) ;Make a digit.
|
||
IDPB T3,T2 ;Store it.
|
||
MOVEI T3,"0"(T4) ;Make a digit.
|
||
IDPB T3,T2 ;Store it.
|
||
MOVEI T3,"0"(T5) ;Make a digit.
|
||
IDPB T3,T2 ;Store it.
|
||
POPJ P, ;All done!
|
||
SUBTTL DETACH - Leave AMIS and visit your local Chinese restaurant
|
||
|
||
DETACH::CALL TTYCLOSE ;Reset terminal parameters
|
||
MOVEI T2,[ASCIZ "From job "]
|
||
CALL OUTSTR
|
||
PJOB T2,
|
||
MOVEI T3,^D10
|
||
CALL OUTNUM
|
||
MOVEI T2,[ASCIZ "
|
||
|
||
."]
|
||
CALL OUTSTR
|
||
CALL TTYWRITE ; write it out,
|
||
CALL TTYFORCE ; and force the buffer!
|
||
MOVSI T1,-1
|
||
ATTACH T1, ;Detach
|
||
JFCL ; Well...
|
||
POPJ P,
|
||
SUBTTL MONITOR - Return to operating system
|
||
|
||
MONITO::CALL TTYCLOSE ;Reset terminal parameters
|
||
MOVE T1,[
|
||
PS.FRC+[.PCDAT
|
||
XWD VECDAT-VECTOR,0
|
||
EXP 0]]
|
||
PISYS. T1, ;Remove attach/detach trap
|
||
JFCL ;Ignore error here
|
||
SKIPN RUNFIL## ;Shall we do /RUN?
|
||
JRST MONI.2 ; No, handle normally.
|
||
MOVEI T1,RUNBLK## ;Load address of run block.
|
||
RUN T1, ;Start the program.
|
||
HALT ;This shall not return.
|
||
MONI.2: MONRT. ;Go to operating system
|
||
MOVE T1,[
|
||
PS.FAC+[.PCDAT
|
||
XWD VECDAT-VECTOR,0
|
||
EXP 0]]
|
||
PISYS. T1, ;Restore attach/detach trap
|
||
JFCL ;Ignore error here
|
||
CALL TTYFLUSH ;Clear internal buffer
|
||
SETZM CCCNT ;Reset ^C counter
|
||
CALL TTYOPEN ;Set terminal parameters again
|
||
MOVE T2,TTFLOW ;Set pref. XonXoff state.
|
||
CALL XONXOFF
|
||
MOVE T2,ACTSTR ;Get address of activation string
|
||
JRST OUTLST ;Print it
|
||
SUBTTL NOINT & OKINT - disable/enable interrupts.
|
||
|
||
NOINT:: AOS INHIBIT
|
||
POPJ P,
|
||
|
||
OKINT:: SOS INHIBIT
|
||
SKIPE CCDONE ;Any deferred interrupt?
|
||
CALL MONITOR ;Yes, exit now.
|
||
SETZM CCDONE ;Wipe flag
|
||
POPJ P,
|
||
SUBTTL PPUSH - Push to exec routine
|
||
|
||
PPUSH:: MOVEM T2,BRKCHR ;Save break character
|
||
MOVEI T1,PTY ;Get PTY channel #
|
||
GETCHR T1, ;Get device characteristics
|
||
JUMPN T1,PPUSH1 ;If not zero, we already got PTY open
|
||
OPEN PTY,[
|
||
EXP UU.FSP!.IOASC
|
||
SIXBIT /PTY/
|
||
XWD PTOBUF,PTIBUF]
|
||
JRST RFALSE ;Can't push.
|
||
MOVE T1,[ ;Set up PTY buffer headers
|
||
XWD 400K,PIBUF1+1]
|
||
MOVEM T1,PTIBUF+.BFADR
|
||
HRRI T1,POBUF1+1
|
||
MOVEM T1,PTOBUF+.BFADR
|
||
MOVE T1,[
|
||
POINT ^D7,0,35]
|
||
MOVEM T1,PTIBUF+.BFPTR
|
||
MOVEM T1,PTOBUF+.BFPTR
|
||
SETZM PTIBUF+.BFCTR
|
||
SETZM PTOBUF+.BFCTR
|
||
|
||
HRLI T1,BUFSIZ+1 ;Get buffer size, plus one
|
||
HRRI T1,PIBUF2+.BFHDR ;Set up PTY buffers
|
||
MOVEM T1,PIBUF1+.BFHDR
|
||
HRRI T1,PIBUF1+.BFHDR
|
||
MOVEM T1,PIBUF2+.BFHDR
|
||
HRRI T1,POBUF2+.BFHDR
|
||
MOVEM T1,POBUF1+.BFHDR
|
||
HRRI T1,POBUF1+.BFHDR
|
||
MOVEM T1,POBUF2+.BFHDR
|
||
|
||
SETZM VECPID+.PSVFL
|
||
MOVE T1,[
|
||
PS.FAC+[EXP PTY
|
||
XWD VECPID-VECTOR,PS.RID
|
||
EXP 0]]
|
||
PISYS. T1, ;Add input done interrupts on PTY
|
||
JRST RFALSE ; Can't add? No push then
|
||
|
||
; Here to give commands to the PTY to set up terminal type.
|
||
|
||
MOVEI T2,"." ;Get a dot
|
||
CALL TTYWRITE ;Play monitor for a while...
|
||
|
||
MOVEI T1,[ASCIZ "TERMINAL TYPE "]
|
||
CALL PTY7ST ;Give string to PTY
|
||
move t1,tttype
|
||
CALL PTY6WD ;Give sixbit word to PTY
|
||
|
||
define $tell(flag,command),<
|
||
movei t1,[asciz " NO"]
|
||
skipn flag
|
||
call pty7st
|
||
movei t1,[asciz " 'command'"]
|
||
call pty7st
|
||
>;$tell macro
|
||
|
||
$tell(ttpage,PAGE)
|
||
$tell(tttab,TAB)
|
||
$tell(ttform,FORM)
|
||
$tell(ttdefr,DEFER)
|
||
|
||
movei t1,[byte (7).CHCRT,.CHNUL]
|
||
pushj p,pty7st ;Terminate command.
|
||
jrst ppush2 ;No need to add interrups again.
|
||
|
||
PPUSH1: SETZM VECPID+.PSVFL
|
||
MOVE T1,[
|
||
PS.FAC+[EXP PTY
|
||
XWD VECPID-VECTOR,PS.RID
|
||
EXP 0]]
|
||
PISYS. T1, ;Add input done interrupts on PTY
|
||
JRST RFALSE ; Can't add? No push then
|
||
MOVEI T1,PTY ;Get subjob channel
|
||
JOBSTS T1, ;Get subjob info
|
||
JRST PPUSH2 ; Hmmmmm... Lose some.
|
||
ANDI T1,JB.UJN ;Extract job #
|
||
HRLS T1 ;Job # to left half...
|
||
HRRI T1,'WAK' ;Function code == wake it up
|
||
PIJBI. T1, ;Rrrrrrriiiiiinnnnngggg!
|
||
JFCL ; Nobody home, I presume.
|
||
|
||
PPUSH2: MOVE T2,DEASTR ;Get pointer to deactivation string
|
||
CALL OUTLST ;Deactivate terminal
|
||
SKIPN CHRCNT ;Type ahead buffer empty?
|
||
JRST PPUSH4 ; Yes, go start looping
|
||
PPUSH3: CALL TTYREAD ;Read the char from type ahead
|
||
SOSGE PTOBUF+.BFCTR ;Room in output buffer?
|
||
OUTPUT PTY, ; No, make some
|
||
IDPB T1,PTOBUF+.BFPTR ;Deposit character
|
||
SKIPE CHRCNT ;Type ahead buffer empty now?
|
||
JRST PPUSH3 ; No, get next byte
|
||
OUTPUT PTY, ;Yes, force out PTY output buffer
|
||
|
||
PPUSH4: SETOM PUSHED ;We are pushed now...
|
||
|
||
PPUSH5: PUSHJ P,PTYSHF ;Shuffle eventual data from PTY.
|
||
MOVEI T1,^D60*^D1000 ;Get sleep time
|
||
HIBER T1,
|
||
JFCL
|
||
SKIPE PUSHED ;Break loop if we are not pushed.
|
||
JRST PPUSH5
|
||
MOVE T1,[
|
||
PS.FRC+[EXP PTY
|
||
XWD VECPID-VECTOR,PS.RID
|
||
EXP 0]]
|
||
PISYS. T1,
|
||
JFCL
|
||
MOVE T2,ACTSTR ;Get pointer to activation string
|
||
CALL OUTLST ;Activate terminal
|
||
CALL TTYFORCE
|
||
MOVEI T1,PTY ;Get PTY channel number
|
||
JOBSTS T1, ;Get Status for subjob
|
||
setz t1,
|
||
TLNN T1,(JB.ULI) ;Job logged in on PTY?
|
||
RELEAS PTY, ; No, don't hold up the PTY
|
||
rtrue: MOVEI T1,1 ;Return true
|
||
MOVEM T1,1(P)
|
||
POPJ P,
|
||
|
||
rfalse: SETZM 1(P) ;Return false
|
||
POPJ P,
|
||
SUBTTL RUNCOM - Start compil with runoffset 1
|
||
|
||
RUNCOM::CALL TTYCLOSE ;Reset line parameters
|
||
MOVSI T1,1 ;Runoffset
|
||
HRRI T1,RUNCMP ;Address of run block
|
||
RUN T1,UU.PHY ;Run the program, from physical SYS:
|
||
HALT .
|
||
|
||
RUNCMP: SIXBIT /SYS/ ;Device
|
||
SIXBIT /COMPIL/ ;Program
|
||
Z ;Unused
|
||
Z ;Unused
|
||
Z ;Unused
|
||
Z ;Unused
|
||
SUBTTL TTYACTIVATION - Get addresses of (de)activation strings.
|
||
|
||
TTYACT::MOVEM T2,ACTSTR ;Save pointer to activation
|
||
MOVEM T3,DEASTR ; and deactivation string
|
||
JRST OUTLST ;Go give activation string to TTY
|
||
SUBTTL TTYCHECK - Look if terminal input buffer is empty
|
||
|
||
TTYCHE::SETZM 1(P) ;Assume we return FALSE
|
||
SKIPE CHRCNT ;Is type ahead buffer empty?
|
||
JRST TTYCH2 ; No, go return TRUE
|
||
JUMPE T2,TTYCH3 ;We go sync output buffer?
|
||
IMULI T2,^D1000 ;Convert seconds to milliseconds
|
||
HRRZ T2,T2 ;Clear flag bits in ac
|
||
HIBER T2, ;Take a nap
|
||
JFCL ;Just ignore error on this one
|
||
TTYCH1: SKIPE CHRCNT ;Wake up, look again
|
||
TTYCH2: AOS 1(P) ; Make result TRUE
|
||
POPJ P, ;Go back
|
||
|
||
TTYCH3: CALL TTYFORCE ;Force output buffer
|
||
SETZM 1(P) ;Reset top of stack
|
||
JRST TTYCH1 ;Go look again
|
||
SUBTTL TTYFLUSH - Flush terminal input buffer
|
||
|
||
TTYFLU::MOVE T1,TAHPTR
|
||
MOVEM T1,TAHGET
|
||
MOVEM T1,TAHPUT
|
||
SETZM CHRCNT
|
||
MOVEI T1,TAHSIZ
|
||
MOVEM T1,CHRGET
|
||
MOVEM T1,CHRPUT
|
||
MOVEM T1,CHREMP
|
||
POPJ P,
|
||
SUBTTL TTYFORCE - Force output buffer
|
||
|
||
TTYFOR::SKIPE DTACHD ;Are we detached?
|
||
POPJ P, ; Yep, keep quiet
|
||
MOVSI T1,770000
|
||
TDNN T1,TTOBUF+.BFPTR ;Anything in buffer?
|
||
POPJ P, ; No, nothing to do.
|
||
OUT TTY, ;Try force out the buffer
|
||
JRST TTYFO2 ;All OK? go syncronize with monitor
|
||
MOVEI T1,^D300
|
||
HIBER T1, ;Else wait a while...
|
||
JFCL
|
||
JRST TTYFOR
|
||
|
||
TTYFO2: MOVE T1,[
|
||
XWD 2,[
|
||
.TOTOC
|
||
-1]]
|
||
TRMOP. T1, ;Read # of chars in monitor buffer
|
||
POPJ P, ;If we can't read, just return
|
||
IMUL T1,FUDGEF ;Estimate I/O time
|
||
SUBI T1,MBFTIM ; and wake a moment earlier...
|
||
JUMPLE T1,TTYFO3 ;Shall we go to bed, madam?
|
||
HIBER T1,
|
||
JFCL
|
||
TTYFO3: POPJ P,
|
||
SUBTTL TTYHACKER - Set/reset hackmatic terminal flag
|
||
|
||
TTYHAC::MOVEM T2,HACKER ;Save new hackmatic terminal flag
|
||
IFN F$META,<
|
||
MOVEI T0,.TOMET+.TOSET ;Load function code.
|
||
SETO T1, ;Argument = my terminal.
|
||
MOVX T3,<3,,T0> ;Arg for TRMOP.
|
||
TRMOP. T3, ;Tell monitor too.
|
||
JFCL ; Ignore error, possibly not implemented here.
|
||
>;End of IFN F$META
|
||
POPJ P,
|
||
;*
|
||
;* Here to read the initial setting of .TOMET from monitor. Called directly
|
||
;* by MAIN.PAS, as a temporary kludge.
|
||
;*
|
||
IFN F$META,<
|
||
TTYMET::MOVE T1,[ ;Load up the arguments.
|
||
XWD 2,[
|
||
EXP .TOMET
|
||
EXP -1]]
|
||
TRMOP. T1, ;Ask monitor.
|
||
SETZ T1, ; Default not meta key on terminal.
|
||
MOVEM T1,1(P) ;Tell MAIN.PAS.
|
||
MOVEM T1,HACKER ;Also remember for TTYREAD.
|
||
POPJ P, ;Return cheerfully.
|
||
>;End of IFN F$META
|
||
|
||
; TTYPROTOCOL - decide if to use ^S/^Q as commands or flow control.
|
||
|
||
TTYPRO::move t1,[xwd 2,[exp .toflo,-1]]
|
||
trmop. t1,
|
||
movei t1,0 ; Default is NO FLOWCONTROL.
|
||
jumpe t1,rfalse ;Zero means use as commands.
|
||
jrst rtrue ;Non-zero means flow control.
|
||
|
||
SUBTTL TTYINIT - Init terminal handler
|
||
|
||
TTYINI::MOVEI T2,TTY ;Try to prevent ?Address check...
|
||
RESDV. T2, ;Release channel if it is there,
|
||
JFCL ; ignore errors.
|
||
MOVE T2,[XWD 2,[EXP .TODEM,-1]]
|
||
TRMOP. T2, ;Read TERMINAL DEFER setting.
|
||
SETZ T2, ; If error, assume NO DEFER.
|
||
movem t2,ttdefr ;Save flag for later use.
|
||
JUMPE T2,FRITZ ;Terminal is NO DEFER, skip kludge.
|
||
MOVE T1,[XWD 3,[EXP .TODEM+.TOSET,-1,0]]
|
||
TRMOP. T1, ;Set NO DEFER
|
||
JRST FROTZ ; Well, skip this then.
|
||
FRITZ: OPEN TTY,[ ;Open then terminal in NOECHO mode,
|
||
EXP IO.SUP ; to bypass bug in TOPS-10.
|
||
SIXBIT /TTY/
|
||
EXP 0]
|
||
JFCL ; Don't care if this fails.
|
||
SETZ T1, ;Clear T1.
|
||
SLEEP T1, ;Take a short nap.
|
||
JUMPE T2,FROTZ ;Don't set DEFER if it was off initially.
|
||
MOVE T1,[XWD 3,[EXP .TODEM+.TOSET,-1,1]]
|
||
TRMOP. T1, ;Set DEFER back on.
|
||
JFCL ; Ignore error.
|
||
FROTZ: OPEN TTY,[ ;Continue and assume SCNSER is in phase now.
|
||
EXP UU.AIO!.IOPIM!UU.PHS
|
||
SIXBIT /TTY/
|
||
XWD TTOBUF,TTIBUF]
|
||
HALT . ; Too bad...
|
||
MOVEI T1,TTY
|
||
IONDX. T1, ;Get UDX for TTY:
|
||
SETO T1, ; Can't happen, but...
|
||
MOVEM T1,TTUDX ;Save UDX
|
||
|
||
define $read(func,save,default<0>),<
|
||
movei t1,func
|
||
pushj p,dtrmop
|
||
movx t1,<default>
|
||
movem t1,save
|
||
>;$read macro
|
||
|
||
$read(.totrm,tttype,<sixbit'TTY '>)
|
||
$read(.topag,ttpage,1)
|
||
$read(.totab,tttab)
|
||
$read(.tofrm,ttform)
|
||
|
||
movei t1,.topbs+.toset;Set an empty PIM mode break set.
|
||
movei t3,0
|
||
pushj p,dtrmop
|
||
jfcl ;Ignore error.
|
||
|
||
; Set up buffer pointers
|
||
|
||
MOVE T1,[XWD 400K,TIBUF1+1]
|
||
MOVEM T1,TTIBUF+.BFADR
|
||
HRRI T1,TOBUF1+1
|
||
MOVEM T1,TTOBUF+.BFADR
|
||
MOVE T1,[POINT ^D8,0,35]
|
||
MOVEM T1,TTIBUF+.BFPTR
|
||
MOVEM T1,TTOBUF+.BFPTR
|
||
SETZM TTIBUF+.BFCTR
|
||
SETZM TTOBUF+.BFCTR
|
||
|
||
HRLI T1,BUFSIZ+1
|
||
HRRI T1,TIBUF2+.BFHDR ;Set up TTY buffers
|
||
MOVEM T1,TIBUF1+.BFHDR
|
||
HRRI T1,TIBUF1+.BFHDR
|
||
MOVEM T1,TIBUF2+.BFHDR
|
||
HRRI T1,TOBUF2+.BFHDR
|
||
MOVEM T1,TOBUF1+.BFHDR
|
||
HRRI T1,TOBUF1+.BFHDR
|
||
MOVEM T1,TOBUF2+.BFHDR
|
||
CALL TTYFLUSH ;Get a clean taye ahead buffer
|
||
|
||
; TTYINIT - Set up PSI system for us
|
||
|
||
MOVEI T1,VECTOR
|
||
PIINI. T1,
|
||
JRST PISYSE
|
||
setzm vectim+.psvfl
|
||
move t1,[
|
||
ps.fac+[.pctmr
|
||
xwd vectim-vector,0
|
||
exp 0]]
|
||
pisys. t1,
|
||
jfcl ;Oh my.
|
||
SETZM VECDAT+.PSVFL
|
||
MOVE T1,[
|
||
PS.FAC+[.PCDAT
|
||
XWD VECDAT-VECTOR,0
|
||
EXP 0]]
|
||
PISYS. T1,
|
||
jfcl ;Funny to have, but...
|
||
SETZM VECJBI+.PSVFL
|
||
MOVE T1,[
|
||
PS.FAC+[.PCJBI
|
||
XWD VECJBI-VECTOR,0
|
||
EXP 0]]
|
||
PISYS. T1,
|
||
jfcl ;Funny to have, but...
|
||
SETZM VECRID+.PSVFL
|
||
MOVE T1,[
|
||
PS.FAC+[EXP TTY
|
||
XWD VECRID-VECTOR,PS.RID
|
||
EXP 0]]
|
||
PISYS. T1,
|
||
JRST PISYSE
|
||
SETZM VECTLE+.PSVFL
|
||
MOVE T1,[
|
||
PS.FAC+[.PCTLE
|
||
XWD VECTLE-VECTOR,0
|
||
EXP 0]]
|
||
PISYS. T1,
|
||
JRST PISYSE
|
||
IFN F$KSYS,<
|
||
MOVE T1,[
|
||
PS.FAC+[.PCKSY
|
||
XWD VECKSY-VECTOR,0
|
||
EXP 0]]
|
||
PISYS. T1,
|
||
jfcl ;Funny to have, but...
|
||
>;End of IFN F$KSYS
|
||
MOVSI T1,(PS.FON)
|
||
PISYS. T1,
|
||
JRST PISYSE
|
||
setom timflg ;Fudge up a timer interrupt.
|
||
SETZM CCCNT ;We have not seen any ^C yet
|
||
SETZM DTACHD ; and we are not detached
|
||
SETZM INHIBIT ;Interrupts are allowed right now
|
||
SETZM CCDONE ;But none pending.
|
||
setzm savttp ;For terminal type listings.
|
||
CALL TTYOPEN ;Set up the rest of the terminal junk
|
||
JRST INDONE ;Simulate input done, pick up typeahead
|
||
|
||
;Routine to do a TRMOP. for our terminal.
|
||
|
||
dtrmop: move t2,ttudx ;Load UDX.
|
||
move t4,[3,,t1]
|
||
trmop. t4, ;Perform the function
|
||
popj p, ; Non-skip return on failure.
|
||
move t1,t4 ;Return value in T1.
|
||
aos (p) ;Do skip return.
|
||
popj p,
|
||
|
||
SUBTTL TTYREAD - Read one character.
|
||
|
||
TTYREA::SKIPG CHRCNT ;Anything to read?
|
||
CALL WAITER ; No, go wait for some
|
||
ILDB T1,TAHGET ;Yes, get it
|
||
SKIPN HACKER ;Using hackmatic terminal?
|
||
ANDI T1,177 ;No, get rid of parity bit
|
||
TRNE T1,200 ;Meta bit?
|
||
TRC T1,200+400 ; Yes, shift it one step left.
|
||
MOVEM T1,1(P) ;Give it to pascal
|
||
SOS CHRCNT
|
||
AOS CHREMP ;Fix up buffer pointers
|
||
SOSLE CHRGET ;Need to wrap get pointer yet?
|
||
POPJ P, ; No, return
|
||
MOVE T1,TAHPTR ;Yes, do the wrap
|
||
MOVEM T1,TAHGET
|
||
MOVEI T1,TAHSIZ
|
||
MOVEM T1,CHRGET
|
||
POPJ P,
|
||
|
||
WAITER: PUSHJ P,TTYFORCE ;Force output buffer meanwhile
|
||
wait.2: movx t2,<sleep t2,> ;Load instruction
|
||
movem t2,hibloc ;Set up for sleeping.
|
||
skipe chrcnt ;Still empty?
|
||
popj p, ; Nope, done waiting
|
||
IFN F$KSYS,<
|
||
SKIPE KSYMSG ;Any KSYS message to print?
|
||
PUSHJ P,KSYOUT ; Yes, go do it.
|
||
>;End of IFN F$KSYS
|
||
skipe timflg ;Timer interrupt?
|
||
pushj p,clkupd ; Yes, update clock.
|
||
movei t2,^D60 ;Load time to sleep.
|
||
xct hibloc ;Sleep or JFCL.
|
||
jrst wait.2 ;Loop back and try again.
|
||
|
||
clkupd: setzm timflg ;Clear flag until next time.
|
||
mstime t2, ;Get time of day.
|
||
idivi t2,^D60000 ;Compute milliseconds until next interrupt.
|
||
movei t2,^D60000
|
||
subi t2,(t3)
|
||
tlo t2,(1B0)
|
||
pitmr. t2, ;Request interrupt.
|
||
jfcl ; Oh my...
|
||
push p,0 ;Push a dummy word (stack frame)
|
||
pushj p,TimeStamp## ;Call mode line clock update routine
|
||
pop p,(p) ;Trim off stack (standard method)
|
||
jrst ttyforce ;Return after a good work (and force buffer)
|
||
;*
|
||
;* PROCEDURE GetClock(VAR Hour, Minute: integer);
|
||
;* This routine are used to get values for mode line clock.
|
||
;*
|
||
getclo::mstime t4, ;Get time of day, in milliseconds.
|
||
idivi t4,^D1000*^D60 ;Get time of day, in minutes.
|
||
idivi t4,^D60 ;Split into hours and minutes.
|
||
movem t4,(t2) ;Return hours.
|
||
movem t5,(t3) ;Return minutes.
|
||
popj p, ;Return to caller
|
||
SUBTTL TTYSPEED - Read terminal speed from monitor
|
||
|
||
TTYSPE::MOVEI T1,.TOTSP
|
||
pushj p,dtrmop
|
||
SETZ T1, ;If error, assume 0
|
||
MOVE T1,SPDTAB(T1) ;Map speed code to baude rate
|
||
MOVEM T1,1(P) ;Give back
|
||
POPJ P,
|
||
|
||
SPDTAB: EXP ^D0 ;Code 0 ...
|
||
EXP ^D50
|
||
EXP ^D75
|
||
EXP ^D110
|
||
EXP ^D134
|
||
EXP ^D150
|
||
EXP ^D200
|
||
EXP ^D300
|
||
EXP ^D600
|
||
EXP ^D1200
|
||
EXP ^D1800
|
||
EXP ^D2400
|
||
EXP ^D4800
|
||
EXP ^D9600
|
||
EXP ^D19200
|
||
EXP ^D0 ; ... 17 ( Octal )
|
||
SUBTTL TTYTYPE - Give terminal type in special code
|
||
|
||
TTYTYP::MOVE T6,T2 ;Save pointer to TERM string
|
||
SETZM 0(T2) ;Clear first word in string
|
||
SETZM 1(T2) ;Clear second word in string
|
||
MOVE T3,[ ;Read TMPcore file, arg block in T4-T5
|
||
XWD .TCRRF,T4]
|
||
DMOVE T4,[
|
||
XWD 'TRM',0 ;File name is TMP:TRM,
|
||
IOWD 2,10] ; read two words into AC 10 and 11
|
||
TMPCOR T3,
|
||
JRST TTYTY3 ;TMP:TRM not found, use TRMOP.(.TOTRM)
|
||
JUMPE T3,TTYTY3 ;Use TRMOP. if file is empty, too
|
||
MOVE T4,[ ;Get a byte pointer to file
|
||
POINT 7,10]
|
||
MOVE T5,[ ;Get a byte pointer to SIXBIT word
|
||
POINT 6,T1]
|
||
SETZ T1,
|
||
MOVEI T7,6 ;Max. # of characters in a SIXBIT word
|
||
|
||
TTYTY1: ILDB T3,T4 ;Get a character
|
||
CAIL T3,"a" ;Lower case alphabetic?
|
||
CAILE T3,"z"
|
||
SKIPA
|
||
SUBI T3,"a"-"A" ;Yes, make it upper case
|
||
CAIL T3,"0" ;Look if character is digit or letter
|
||
CAILE T3,"9"
|
||
SKIPA ;Not digit, look if letter
|
||
JRST TTYTY2
|
||
CAIL T3,"A"
|
||
CAILE T3,"Z"
|
||
JRST TTYTY4 ;Not letter either, break loop
|
||
TTYTY2: SUBI T3,"A"-'A' ;Convert character from ASCII to SIXBIT
|
||
IDPB T3,T5 ;Put character in SIXBIT word
|
||
SOJG T7,TTYTY1 ;Loop back if we got more room
|
||
;Now we got sixbit word in T1, go look
|
||
JRST TTYTY4 ; it up in the terminal type table.
|
||
|
||
TTYTY3:
|
||
IFN F$SUBTYP,<
|
||
MOVE T1,[XWD 2,[EXP .TOSUB,-1]]
|
||
TRMOP. T1, ;Get SUBTYPE, if we have it.
|
||
MOVEI T1,0 ; Error -- say nothing.
|
||
TLNN T1,-1 ;Left half zero?
|
||
>;End IFN F$SUBTYP
|
||
MOVE T1,tttype
|
||
ttyty4: MOVEI T7,6 ;Transfer 6 characters
|
||
HRLI T6,(POINT 7) ;Build byte pointer to TERM string
|
||
MOVE T5,[ ;Build byte pointer to SIXBIT name
|
||
POINT 6,T1]
|
||
TTYTY5: ILDB T0,T5 ;Get a byte
|
||
ADDI T0,"A"-'A' ;Make it ASCII
|
||
IDPB T0,T6 ;Give it to TERM
|
||
SOJG T7,TTYTY5 ;Loop back if more
|
||
MOVEM T1,TTNAME ;Remember the terminal name for later.
|
||
CAME T1,['VT100 '] ;Is this a VT100?
|
||
TDZA T1,T1 ; Nope, return zero.
|
||
MOVEI T1,1 ; Yes, the only one from now on...
|
||
MOVEM T1,1(P) ;Give back 0 or 3.
|
||
POPJ P,
|
||
|
||
SUBTTL BADTTY - tell user his terminal type is not supported.
|
||
|
||
BADTTY::SETZM ACTSTR ;Clear activation string pointer
|
||
SETZM DEASTR ;Clear deactivation string pointer
|
||
MOVEI T2,[
|
||
ASCIZ "
|
||
The terminal type "]
|
||
CALL OUTSTR ;Print first half of short message.
|
||
MOVE T2,TTNAME ;Get terminal name.
|
||
SETZ T3, ;Clear junk.
|
||
CALL OUTSIX ;Print terminal name.
|
||
MOVEI T2,[
|
||
ASCIZ " is not supported by AMIS.
|
||
Type 'CONTINUE' for further information.
|
||
"]
|
||
CALL OUTSTR ;Print second half of short message.
|
||
BADT.2: CALL MONITOR ;Exit to operating system.
|
||
SKIPN SAVTTP
|
||
JRST[ MOVEI T2,NTTMSG
|
||
CALL OUTSTR
|
||
JRST BADT.2]
|
||
MOVEI T2,[ASCIZ "
|
||
The following terminals are supported:
|
||
|
||
"]
|
||
CALL OUTSTR
|
||
movei t1,0
|
||
jsp t7,stor.c
|
||
MOVEI T2,SAVTTL
|
||
CALL OUTSTR
|
||
MOVEI T2,[ASCIZ "
|
||
|
||
Use the monitor command 'TERMINAL TYPE <name>' to set
|
||
the terminal type.
|
||
"]
|
||
CALL OUTSTR
|
||
JRST BADT.2
|
||
|
||
nttmsg: asciz "
|
||
There are no terminals defined. Contact your friendly systems programmer.
|
||
|
||
"
|
||
|
||
SaveTerminalName::
|
||
MOVE T4,[point 7,t2]
|
||
MOVEI t5,6
|
||
SKIPE SAVTTP ;Set up yet?
|
||
JRST ss4711 ; Yes, skip this.
|
||
setzm savnum
|
||
MOVE T1,[POINT 7,SAVTTL]
|
||
MOVEM T1,SAVTTP
|
||
MOVEI T1,<<5*SAVLEN>-1>
|
||
MOVEM T1,SAVCNT
|
||
ss4711: ildb t1,t4 ;get byte...
|
||
jsp t7,stor.c
|
||
sojg t5,ss4711 ;Maybe loop.
|
||
movei t1," "
|
||
jsp t7,stor.c
|
||
jsp t7,stor.c
|
||
aos t1,savnum
|
||
caige t1,8
|
||
popj p,
|
||
movei t1,15
|
||
jsp t7,stor.c
|
||
movei t1,12
|
||
jsp t7,stor.c
|
||
setzm savnum
|
||
popj p,
|
||
|
||
stor.c: sosle savcnt ;room?
|
||
idpb t1,savttp ; room. store.
|
||
jrst (t7) ;return.
|
||
SUBTTL TTYWIDTH - Read terminal width from monitor
|
||
|
||
TTYWID::MOVEI t1,.TOWID
|
||
pushj p,dtrmop
|
||
MOVEI T1,^D80 ;If error, assume page width is 80
|
||
MOVEM T1,1(P) ;Store the result
|
||
POPJ P,
|
||
|
||
; TTYPRINTABLE - Return set of printable chars.
|
||
|
||
TTYPRI::movei 1,<000000,,000017>
|
||
movem 1,0(2)
|
||
setom 1(2)
|
||
setom 2(2)
|
||
movx 1,<777777,,400000>
|
||
movem 1,3(2)
|
||
popj p,
|
||
|
||
SUBTTL TTYLENGTH - override default terminal length, if possible.
|
||
|
||
ttylen::push p,t2 ;Save argument.
|
||
movei t1,.tolnb
|
||
pushj p,dtrmop ;Read terminal length.
|
||
setz t1, ; Default length.
|
||
pop p,t2 ;Restore argument pointer.
|
||
jumple t1,.popj ;Don't overwrite default with junk.
|
||
movem t1,(t2) ;Store new value.
|
||
popj p, ;Return.
|
||
|
||
SUBTTL TTYWRITE - write one character.
|
||
|
||
TTYWRI::SKIPE DTACHD ;Are we detached?
|
||
POPJ P, ; Yep, keep quiet
|
||
IFN F$OPAR,<
|
||
MOVEI T1,(T2) ;Copy char
|
||
LSH T1,-4 ;Shift...
|
||
XORI T1,(T2) ;Get together...
|
||
TRCE T1,14
|
||
TRNN T1,14
|
||
TRC T2,200
|
||
TRCE T1,3
|
||
TRNN T1,3
|
||
TRC T2,200
|
||
>;End of IFN F$OPAR
|
||
SOSGE TTOBUF+.BFCTR ;Room in buffer?
|
||
JRST TTYWR2 ; No, go force out
|
||
IDPB T2,TTOBUF+.BFPTR ;Deposit
|
||
POPJ P, ;Done!
|
||
|
||
TTYWR2: OUT TTY, ;Out with the buffer
|
||
JRST TTYWRITE ; OK, but we may have been detached.
|
||
MOVEI T1,^D300 ;Time to sleep
|
||
HIBER T1, ;Take a nap
|
||
JFCL ; Ignore error return,
|
||
JRST TTYWRITE ; and hope for better luck
|
||
SUBTTL USRNAME - Put user name in argument string
|
||
|
||
USRNAM::CALL BLANKS ;Put blanks in all of string T2 points to
|
||
HRLI T2,(POINT 7) ;Make argument a byte pointer
|
||
HRROI T3,.GTNM1 ;Set up to get first
|
||
HRROI T4,.GTNM2 ; and second half of user name
|
||
GETTAB T3,
|
||
SKIPA
|
||
GETTAB T4,
|
||
SETZB T3,T4 ; In case of errors, clear both words.
|
||
USRNM1: LDB T1,[ ;Get first sixbit char
|
||
POINT ^D6,T3,^D5]
|
||
ADDI T1,"A"-'A' ;Make it ascii
|
||
IDPB T1,T2
|
||
LSHC T3,6 ;Shift both T6 and T7
|
||
JUMPN T3,USRNM1 ;Loop back if any of them
|
||
JUMPN T4,USRNM1 ; is non-zero
|
||
POPJ P,
|
||
;I/O routines for PTY
|
||
|
||
; Interrupt routine to flag data ready.
|
||
|
||
PTYDON: SETOM PTYFLG ;Remember to try to read sometime.
|
||
DEBRK. ;Dismiss interrupt.
|
||
JFCL ; Can't happen.
|
||
POPJ P, ;Can happen.
|
||
|
||
; Actual reader, called by background loop.
|
||
|
||
PTYSHF: SKIPN PTYFLG ;Any data to shuffle from PTY?
|
||
POPJ P, ; No, return now.
|
||
SETZM PTYFLG ;Yes, but clear flag.
|
||
SHFLUP: INPUT PTY, ;Get info from PTY
|
||
SKIPG PTIBUF+.BFCTR ;Did we get anything?
|
||
JRST TTYFORCE ; No more data, force terminal buffers.
|
||
SHFL.2: SOSGE PTIBUF+.BFCTR ;Decrement buffer counter
|
||
JRST SHFLUP ; No more, try for another buffer.
|
||
ILDB T2,PTIBUF+.BFPTR ;Get a byte
|
||
CALL TTYWRITE ;Write it on terminal
|
||
JRST SHFL.2 ; and loop back for more
|
||
|
||
;; Routine to give an ASCIZ string to the PTY.
|
||
|
||
PTY7ST: HRLI T1,(POINT ^D7) ;Get a byte pointer to the string
|
||
PTY7S1: ILDB T2,T1 ;Get a byte from the string
|
||
JUMPE T2,PTY7S2 ;Break on null
|
||
SOSGE PTOBUF+.BFCTR ;Look if more foom in PTY output buffer
|
||
OUTPUT PTY, ; Make more room then!
|
||
IDPB T2,PTOBUF+.BFPTR ;Deposit byte in buffer
|
||
JRST PTY7S1 ;Loop back and look if more
|
||
|
||
PTY7S2: OUTPUT PTY, ;Finally, force out the buffer
|
||
POPJ P, ; and return to caller
|
||
|
||
;; Routine to give SIXBIT word in T1 to the PTY.
|
||
|
||
PTY6WD: LDB T2,[ ;Get first character
|
||
POINT ^D6,T1,^D5]
|
||
ADDI T2,"A"-'A' ;Convert SIXBIT to ASCII
|
||
SOSGE PTOBUF+.BFCTR ;Room in buffer?
|
||
OUTPUT PTY, ; No, make some
|
||
IDPB T2,PTOBUF+.BFPTR ; then deposit character
|
||
LSH T1,6 ;Shift out one character
|
||
JUMPN T1,PTY6WD ;Loop back if more in word
|
||
OUTPUT PTY, ;No more, force out buffer
|
||
POPJ P, ; and return to caller
|
||
SUBTTL Routine to set up terminal parameters
|
||
|
||
TTYOPE: movei t1,.tocom
|
||
pushj p,dtrmop
|
||
setz t1,
|
||
jumpe t1,TTYOP1 ;Look if we are in monitor mode
|
||
movei t1,.todsp
|
||
movei t3,msgnmm
|
||
pushj p,dtrmop
|
||
jfcl
|
||
MONRT. ;Exit to monitor
|
||
JRST TTYOPEN ;Try again
|
||
|
||
TTYOP1: SETSTS TTY,.IOPIM ;Reset PIM mode on TTY
|
||
MOVEI T5,TTY ;Get TTY channel #
|
||
IONDX. T5, ;Get UDX for channel
|
||
SETO T5, ; Can't happen, but...
|
||
MOVEM T5,TTUDX ;Save UDX
|
||
CALL TTYSPEED ;Compute fudge factor
|
||
SKIPG T1,2(P)
|
||
MOVEI T1,^D9600
|
||
MOVEI T2,^D10K
|
||
IDIV T2,T1
|
||
MOVEM T2,FUDGEF ;Save new fudge factor
|
||
POPJ P,
|
||
SUBTTL Routine to reset terminal parameters
|
||
|
||
TTYCLO: MOVE T2,DEASTR ;Get address of deactivation string
|
||
CALL OUTLST ;Print string
|
||
CALL TTYFORCE ;Force out buffers
|
||
SKIPA T2,TTPAGE ;Get previous page mode setting.
|
||
|
||
;* Skip into XonXoff handler.
|
||
|
||
XONXOF::MOVEM T2,TTFLOW ;Save pref. xonxoff state.
|
||
MOVEI T0,.TOPAG+.TOSET;Function code.
|
||
MOVE T1,TTUDX ;Device index.
|
||
MOVX T3,<3,,T0> ;Argument pointer.
|
||
TRMOP. T3, ;Set new value.
|
||
JFCL ; Ignore error.
|
||
JUMPN T2,.POPJ ;If setting XonXoff mode, done.
|
||
MOVEI T0,.TOSTP+.TOSET
|
||
MOVX T3,<3,,T0> ;Else we have to make sure the terminal don't
|
||
TRMOP. T3, ; get stuck in XOFF state...
|
||
JFCL
|
||
POPJ P, ;Return.
|
||
SUBTTL Some junk...
|
||
|
||
BLANKS: MOVE T3,[ ;Blank string
|
||
BYTE(7) " "," "," "," "," "]
|
||
MOVEM T3,(T2) ;Put blanks in first word
|
||
HRL T3,T2 ;Source in left halfword
|
||
HRRI T3,1(T2) ;Dest in right
|
||
BLT T3,<STRSIZ/5>-1(T2) ;Blank rest of string
|
||
POPJ P,
|
||
|
||
OUTLST: JUMPE T2,.POPJ ;Any pointer there?
|
||
SKIPG T3,(T2) ;Anything to type out?
|
||
POPJ P,
|
||
HRRI T7,1(T2)
|
||
HRLI T7,(POINT 7)
|
||
OUTLS1: ILDB T2,T7
|
||
CALL TTYWRITE
|
||
SOJG T3,OUTLS1
|
||
.POPJ: POPJ P,
|
||
|
||
OUTSTR: MOVE T7,T2
|
||
HRLI T7,(POINT 7)
|
||
OUTST1: ILDB T2,T7
|
||
JUMPE T2,.POPJ
|
||
CALL TTYWRITE
|
||
JRST OUTST1
|
||
SUBTTL Input done interrupt routine
|
||
|
||
INDONE: MOVEM T1,INSAVE ;Save AC 1
|
||
INDON1: SOSGE TTIBUF+.BFCTR ;More chars in buffer?
|
||
JRST GETBUF ; No, go get a buffer
|
||
ILDB T1,TTIBUF+.BFPTR ;Get a char from buffer
|
||
SKIPE PUSHED ;Look if we are pushed
|
||
JRST PTYPUT ; We are, give char to PTY
|
||
INDON2: CAIE T1,.CHCNC ;Is char C-C
|
||
CAIN T1,.CHCNC+METACH ; or C-M-C?
|
||
JRST INDON4 ; Yep, go look if we had enough
|
||
SETZM CCCNT ;No, clear counter
|
||
INDON3: SOSGE CHREMP ;Is there space to put this char in?
|
||
JRST INDON5 ; Nope, go beep the user
|
||
IDPB T1,TAHPUT ;Yes, put it there
|
||
AOS CHRCNT ;Increment # of chars in buffer
|
||
SOSLE CHRPUT ;Decrement wrap pointer
|
||
JRST INDON1 ; We need not wrap yet, loop back
|
||
MOVE T1,TAHPTR
|
||
MOVEM T1,TAHPUT ;Do the wrap
|
||
MOVEI T1,TAHSIZ
|
||
MOVEM T1,CHRPUT
|
||
JRST INDON1 ;Loop back
|
||
|
||
IFN F$DBUG,< ;If debugging, pretend we have
|
||
INDON4: MOVEI T1,$0BPT##+1 ; a breakpoint at the interrupted
|
||
EXCH T1,VECRID+.PSVOP; instruction.
|
||
MOVEM T1,$0BPT##
|
||
MOVE T1,INSAVE ;Restore T1 for us
|
||
OUTSTR[ ASCIZ /
|
||
****************************************************
|
||
******** DDT (Type <ESC>P to continue) ********
|
||
****************************************************
|
||
/]
|
||
JRST INTEND ;DEBRK. rigth into DDT!
|
||
>;End IFN F$DBUG
|
||
IFE F$DBUG,<
|
||
INDON4: AOS T1,CCCNT ;Increment ^C count, put result in T1
|
||
CAIGE T1,CCMAX ;Greater than max # allowed?
|
||
JRST INDON6 ; No, go return this char
|
||
SKIPLE INHIBIT ;Are we allowed to break here?
|
||
AOSA CCDONE ; No, set flag to break as soon as possible
|
||
SKIPA
|
||
JRST INDON6 ; and forget this
|
||
MOVEM T0,SAVEB2 ;Save AC 0
|
||
MOVE T0,[ ;Set up a BLT pointer
|
||
XWD T1,SAVEB2+1]
|
||
BLT T0,SAVEB2+17 ;Save all the other AC's
|
||
MOVE T0,[
|
||
XWD PDLP2,15]
|
||
BLT T0,17 ;Move in a new stack
|
||
CALL MONITOR ;Go to operating system
|
||
MOVE T0,[ ;Get a BLT pointer
|
||
XWD SAVEB2+1,T1]
|
||
BLT T0,17 ;Restore all AC's
|
||
MOVE T0,SAVEB2 ;Restore AC 0 too
|
||
SETZM CCCNT ;Zero ^C counter
|
||
JRST INDON1 ;Loop back
|
||
>;End IFE F$DBUG
|
||
SUBTTL Continuing input done routines.
|
||
|
||
INDON5: AOS CHREMP
|
||
OUTCHR[ EXP .CHBEL]
|
||
JRST INDON1
|
||
|
||
INDON6: LDB T1,TTIBUF+.BFPTR ;Get ^C type character again
|
||
JRST INDON3 ;Go back, process as normal char
|
||
|
||
GETBUF: IN TTY,
|
||
JRST INDON1
|
||
movx t1,<jfcl>
|
||
movem t1,hibloc
|
||
MOVE T1,INSAVE
|
||
DEBRK.
|
||
jfcl ;Can't happen.
|
||
POPJ P,
|
||
|
||
OUTPUT PTY,
|
||
PTYPUT: SKIPN HACKER ;Eight bit terminal?
|
||
ANDI T1,177 ; No, mung parity bit
|
||
CAMN T1,BRKCHR ;Is this the break character?
|
||
JRST PTYPU2 ; Yep, pop it up a little
|
||
SOSGE PTOBUF+.BFCTR
|
||
JRST PTYPUT-1 ;*** Kludgy ***
|
||
IDPB T1,PTOBUF+.BFPTR
|
||
OUTPUT PTY,
|
||
JRST INDON1
|
||
|
||
PTYPU2: SETZM PUSHED
|
||
JRST INDON1
|
||
SUBTTL PSI handling -- KSYS warnings
|
||
;*
|
||
;* KSYS interrupts go here.
|
||
;*
|
||
IFN F$KSYS,<
|
||
KSYS: DMOVEM T1,KSYSAV ;Save a couple.
|
||
MOVEM T3,KSYSAV+2 ;... and another...
|
||
SKIPG T1,VECKSY+.PSVIS;Get time left until KSYS
|
||
AOJN T1,KSYS.2 ; Ignore zero, change -1 to 0.
|
||
MOVSI T2,-KSYLEN ;Load length of KSYS checkpoint table
|
||
KSYS.1: MOVS T3,KSYTAB(T2) ;Get table entry. (swapped)
|
||
CAIN T1,(T3) ;Is this the it?
|
||
HLRZM T3,KSYMSG ; Yes, remember pointer to message.
|
||
AOBJN T2,KSYS.1 ;Loop if more table
|
||
KSYS.2: MOVE T3,KSYSAV+2 ;Restore T3.
|
||
DMOVE T1,KSYSAV ;Restore T1 & T2.
|
||
JRST INTEND ;Dismiss the interrupt.
|
||
;*
|
||
;* When the time left until KSYS is equal to one of the entries in KSYTAB,
|
||
;* we issue a warning on the users terminal.
|
||
;*
|
||
KSYTAB: XWD ^D0,[ASCIZ "is over!!!"]
|
||
XWD ^D1,[ASCIZ "ends in one minute"]
|
||
XWD ^D2,[ASCIZ "ends in two minutes"]
|
||
XWD ^D5,[ASCIZ "ends in five minutes"]
|
||
XWD ^D15,[ASCIZ "ends in fifteen minutes"]
|
||
KSYLEN==.-KSYTAB
|
||
;*
|
||
;* This is the routine that gets called when KSYMSG gets non-zero.
|
||
;*
|
||
KSYOUT: MOVEI T2,[ ;Load start of KSYS message.
|
||
BYTE(7) .CHBEL, .CHCRT, .CHLFD, "*", "*"
|
||
ASCIZ "*** Timesharing "]
|
||
PUSHJ P,OUTSTR ;Print string on terminal
|
||
MOVE T2,KSYMSG ;Get main message.
|
||
PUSHJ P,OUTSTR ;Print it.
|
||
MOVEI T2,[
|
||
ASCIZ " *****"]
|
||
PUSHJ P,OUTSTR ;Print final part.
|
||
PUSHJ P,TTYFORCE ;Force out TTY buffers
|
||
SETZM KSYMSG ;We did it now, don't do it again.
|
||
POPJ P, ;Return to caller.
|
||
>;End IFN F$KSYS
|
||
SUBTTL Attach/detach trap
|
||
|
||
ATTDET: SKIPGE VECDAT+.PSVIS ;Look if it was a detach
|
||
JRST ATTDE2 ; It was
|
||
MOVEM 17,SAVEB2+17 ;Save AC 17
|
||
MOVEI 17,SAVEB2
|
||
BLT 17,SAVEB2+16 ;Save the rest
|
||
MOVE 15,PDLP2 ;Get new AC 15
|
||
DMOVE 16,PDLP2+1 ;Get new AC 16 & 17
|
||
movei t1,.todsp
|
||
movei t3,msgatt
|
||
pushj p,dtrmop
|
||
jfcl
|
||
CALL MONITOR ;Go to operating system
|
||
SETZM DTACHD
|
||
SKIPE PUSHED ;Are we pushed?
|
||
JRST ATTDE1 ; Yep, don't refresh screen.
|
||
PUSH P,1(P) ;ADJSP P,1
|
||
CALL WINREFRESH## ;Restore jumbled screen
|
||
CALL WINUPDATE## ;Allow updating...
|
||
POP P,(P) ;ADJSP P,-1
|
||
ATTDE1: HRLZI 17,SAVEB2
|
||
BLT 17,17
|
||
JRST INTEND
|
||
|
||
ATTDE2: SETOM DTACHD ;We are detached now
|
||
CLRBFO ;Clear output buffer
|
||
JRST INTEND ;Dismiss!
|
||
SUBTTL Internal error messages.
|
||
|
||
MSGATT: BYTE(7) .CHCRT,"Y","o","u"," "
|
||
ASCIZ "have attached a job running AMIS.
|
||
Type 'CONTINUE' to resume editing."
|
||
|
||
MSGNMM: BYTE(7) .CHCRT,"S","o","r","r"
|
||
ASCIZ "y, I can't work in monitor mode"
|
||
SUBTTL Other interrupt routines
|
||
|
||
timint: setom timflg ;Just flag timer interrupt.
|
||
|
||
tlx: jrst intend ;Ignore time limit exceeded
|
||
|
||
CROSS: movem t1,savcrs ;Save T1.
|
||
HRRZ T1,VECJBI+.PSVIS
|
||
CAIE T1,'POP'
|
||
jrst crosse
|
||
MOVEI T1,PTY ;Get PTY channel
|
||
JOBSTS T1, ;Get job status for subjob
|
||
JRST CROSSE ; Error, ignore pop request
|
||
HRL T1,T1 ;Move job # to left half word
|
||
HRRI T1,'POP' ;Get function code
|
||
CAMN T1,VECJBI+.PSVIS ;Interrupted by our own subjob?
|
||
SETZM PUSHED ; Yes, not pushed any more
|
||
CROSSE: move t1,savcrs ;Restore T1
|
||
INTEND: movem t1,hibloc ;Save t1.
|
||
movx t1,<jfcl> ;Load instruction.
|
||
exch t1,hibloc ;Restore t1, set up hiber location.
|
||
debrk.
|
||
jfcl
|
||
PISYSE: MOVEI T2,[ASCIZ "TTYIO: Some PISYS function failed."]
|
||
JRST BUG
|
||
SUBTTL Some internal I/O routines
|
||
|
||
OUTNUM: MOVE T7,T2 ;Move number to T7
|
||
OUTNU2: IDIV T7,T3 ;The standard recursive
|
||
PUSH P,T7+1 ; number printing routine.
|
||
SKIPE T7
|
||
CALL OUTNU2
|
||
POP P,T2
|
||
ADDI T2,"0"
|
||
JRST TTYWRITE
|
||
|
||
OUTSIX: DMOVE T6,T2 ;Get words into T6 & T7
|
||
OUTSI1: LDB T2,[ ;Get first sixbit char
|
||
POINT ^D6,T6,^D5]
|
||
ADDI T2,"A"-'A' ;Make it ascii
|
||
CALL TTYWRITE
|
||
LSHC T6,6 ;Shift both T6 and T7
|
||
JUMPN T6,OUTSI1 ;Loop back if any of them
|
||
JUMPN T7,OUTSI1 ; is non-zero
|
||
POPJ P,
|
||
SUBTTL Low segment data areas
|
||
|
||
XLIST
|
||
LIT
|
||
LIST
|
||
|
||
RELOC 0 ;Put data in low segment
|
||
|
||
VECTOR: ;Start of PSI vector here
|
||
VECTIM: EXP TIMINT ;Slot for timer interrupts.
|
||
BLOCK 3
|
||
VECDAT: EXP ATTDET ;Slot for attach/detach
|
||
BLOCK 3
|
||
VECJBI: EXP CROSS ;Slot for cross job interrupts
|
||
BLOCK 3
|
||
VECRID: EXP INDONE ;Slot for input done
|
||
BLOCK 3
|
||
VECPID: EXP PTYDON ;Slot for PTY input done
|
||
BLOCK 3
|
||
VECTLE: EXP TLX ;Slot for time limit exceeded
|
||
BLOCK 3
|
||
IFN F$KSYS,<
|
||
VECKSY: EXP KSYS ;Slot for KSYS warnings.
|
||
BLOCK 3
|
||
>;End IFN F$KSYS
|
||
VECEND: ;End of PSI vector here
|
||
|
||
ACTSTR: BLOCK 1 ;Pointer to activation string
|
||
BRKCHR: BLOCK 1 ;Break char, when pushing
|
||
CCCNT: BLOCK 1 ;^C counter
|
||
CCDONE: BLOCK 1 ;Non-zero means inhibited ^C trap
|
||
; should be served
|
||
DEASTR: BLOCK 1 ;Pointer to deactivation string
|
||
DTACHD: BLOCK 1 ;Detach flag (set if job is detached)
|
||
FUDGEF: BLOCK 1 ;Fudge factor
|
||
HACKER: BLOCK 1 ;Flag for hackmatic terminal
|
||
HIBLOC: SLEEP T2, ;Instruction to execute for sleeping.
|
||
INHIBIT:BLOCK 1 ;Non-zero means inhibit ^C exits from
|
||
; interrupt level
|
||
INSAVE: BLOCK 1 ;Save T1 here when input done interrupt
|
||
IFN F$KSYS,<
|
||
KSYMSG: BLOCK 1 ;Pointer to KSYS message to print sometime.
|
||
KSYSAV: BLOCK 3 ;Place to save T1-T3 when checking KSYS.
|
||
>;End of IFN F$KSYS
|
||
PUSHED: BLOCK 1 ;If we are pushed or not
|
||
PTYFLG: BLOCK 1 ;PTY has data ready.
|
||
|
||
TIMFLG: BLOCK 1 ;Timer interrupt flag.
|
||
|
||
;Various terminal parameters, set up mainly by TTYINIT.
|
||
|
||
ttname: block 1 ;Holds terminal name, in sixbit.
|
||
tttype: block 1 ;Holds terminal type. (.TOTRM)
|
||
ttdefr: block 1 ;Holds terminal defer flag. (.TODEM)
|
||
tttab: block 1 ;Holds terminal tabs flag. (.TOTAB)
|
||
ttform: block 1 ;Holds terminal form flag. (.TOFRM)
|
||
ttudx: block 1 ;Holds UDX for TTY:
|
||
ttflow: block 1 ;Pref. xonxoff state inside editor.
|
||
ttpage: block 1 ;Pref. xonxoff state outside editor.
|
||
|
||
TTOBUF: BLOCK 3 ;Terminal output buffer header
|
||
TOBUF1: BLOCK 3+BUFSIZ
|
||
TOBUF2: BLOCK 3+BUFSIZ
|
||
|
||
TTIBUF: BLOCK 3 ;Terminal input buffer header
|
||
TIBUF1: BLOCK 3+BUFSIZ
|
||
TIBUF2: BLOCK 3+BUFSIZ
|
||
|
||
PTOBUF: BLOCK 3 ;PTY output buffer header
|
||
POBUF1: BLOCK 3+BUFSIZ
|
||
POBUF2: BLOCK 3+BUFSIZ
|
||
|
||
PTIBUF: BLOCK 3 ;PTY input buffer header
|
||
PIBUF1: BLOCK 3+BUFSIZ
|
||
PIBUF2: BLOCK 3+BUFSIZ
|
||
|
||
CHRCNT: BLOCK 1 ;# of internally bufferd characters
|
||
CHREMP: BLOCK 1 ;# of empty positions in tah buffer
|
||
CHRGET: BLOCK 1 ;Wrap counter for get pointer
|
||
CHRPUT: BLOCK 1 ;Wrap counter for put pointer
|
||
TAHGET: BLOCK 1 ;Current get pointer
|
||
TAHPUT: BLOCK 1 ;Current put pointer
|
||
TAHPTR: POINT ^D8,TAHBUF ;Pure pointer to type ahead buffer
|
||
TAHBUF: BLOCK <TAHSIZ+^D3>/^D4 ;Internal type ahead buffer
|
||
|
||
savttp: block 1
|
||
savcnt: block 1
|
||
savnum: block 1
|
||
savttl: block <savlen==100>
|
||
|
||
SAVEB2: BLOCK 20
|
||
savcrs: block 1 ;Save T1 here on cross job interrupt.
|
||
PDLP2: EXP PDL2+PDLLEN-10
|
||
XWD PDL2,PDL2
|
||
XWD 400K,PDL2+1
|
||
PDL2: BLOCK PDLLEN
|
||
|
||
END
|