.title k11rtt mt terminal service for Kermit-11/RT .ident /1.0.01/ ; 28-May-84 09:06:31 Brian Nelson ; ; Copyright (C) 1984 Change Software, Inc. .if ndf, K11INC .ift .include /IN:K11MAC.MAC/ .endc .psect .sbttl definitions for multiple terminal support .mcall .mtstat ,.mtatch,.mtdtch,.mtget ,.mtin .mcall .mtout ,.mtprnt,.mtrcto,.mtset .mcall .mrkt ,.cmkt ,.twait ,.ttinr .enabl gbl m.tsts = 0 ; terminal status word m.tst2 = 2 ; terminal status word number 2 m.tfil = 4 ; character requiring fill m.fcnt = 5 ; number of fillers m.twid = 6 ; width m.tstw = 7 ; terminal status byte m.nlun = 4 ; number of terminals for .mtstat .macro $mterr ; map multiple terminal service movb @#errbyt,r0 ; into a global error code asl r0 ; simple to do mov mterr(r0),r0 ; thats all there is to it .endm $mterr .save .psect mtmap ,rw,d,lcl,rel,con lunmap: .blkw 12 ; map LUNS to RT units mtsts: .blkw 10 ; from the .mtstat call ttsts: .blkw 10 ; for ttyini tmowrk: .blkw 10 ; for mark time while reading ttsave: .blkw 4 ttctlc: .blkw 1 ; for control C things in connect mode ttime: .word 0,1 ; a tick sleep for .twait .restore .sbttl assign the terminal unit m.assdev:: save ; we may want to use these .mtstat #rtwork ,#mtsts ; get terminal driver status bcs 90$ ; oops tst mtsts+m.nlun ; any multi tty support in exec? beq 80$ ; no, thats fatal call ttpars ; parse the device unit number bcs 70$ ; bad device name mov r0 ,r1 ; save the unit number now .mtatch #rtwork,#kbiost,r1 ; try to attach the terminal now bcs 90$ ; fatal error, exit clr r0 ; ok, exit with success br 100$ ; bye 70$: mov #er$dev ,r0 ; return bad device name error br 100$ ; bye 80$: mov #er$sup ,r0 ; return missing support error br 100$ ; bye 90$: $mterr ; map local error into global error 100$: unsave ; pop local registers and exit return m.deadev:: save ; save this one, folks call ttpars ; parse the device name bcs 70$ ; oops mov r0 ,r1 ; save the unit number now .mtdtch #rtwork,r1 ; do it clr r0 ; success br 100$ ; bye 70$: mov #er$dev ,r0 ; bad device name error br 100$ ; bye 100$: unsave ; exit return ; dh .sbttl initialize the terminal ; T T Y I N I ; ; input: @r5 device name ; 2(r5) LUN ; 4(r5) modifiers ; ; output: r0 error code ttmode = 100 ! 10000 ! 40000 m.ttyini:: save ; we will need this one call ttpars ; get the unit number bcs 70$ ; oops, return ER$DEV error mov 2(r5) ,r1 ; get the internal LUN to use asl r1 ; into a word offset mov r0 ,lunmap(r1) ; so we can map lun into a unit movb #377 ,lunmap+1(r1) ; say we have done this already mov r0 ,r1 ; save the unit number please .mtatch #rtwork,#kbiost,r1 ; ensure it's attached mov #ttsts ,r2 ; point to the status area .mtget #rtwork,r2,r1 ; get the current terminal setting bcs 90$ ; oops bic #2 ,m.tsts(r2) ; no automatic cr/lf's please bis #ttmode ,m.tsts(r2) ; no lower case convert, no echo bis #200!100000,m.tst2(r2) ; read and write pass all please .mtset #rtwork,r2,r1 ; set these please bcs 90$ ; oops mov #1000 ,r2 10$: calls binrea ,<2(r5),#-1> ; eat anything that's pending please dec r2 ; don't loop forever please beq 20$ ; exit the loop tst r0 ; did we get anything at all ? beq 10$ ; yes, eat some more input 20$: clr r0 ; all done br 100$ ; bye 70$: mov #er$dev ,r0 ; device name parse failed br 100$ ; bye 90$: $mterr ; map local error into a global one 100$: unsave ; pop and exit return .sbttl save/restore terminal settings m.ttysav:: save ; we will use this one call ttpars ; parse the unit number please bcs 80$ ; oops mov r0 ,r1 ; copy the parsed unit number .mtget #rtwork,#ttparm,r1 ; get the current settings bcs 90$ ; error clr r0 ; success br 100$ ; bye 80$: mov #er$dev ,r0 ; bad device name br 100$ ; bye 90$: $mterr ; error, map into global and exit 100$: unsave ; pop this and exit return m.ttyrst:: save ; we will use this one clr r2 ; was already attached call ttpars ; parse the unit number please bcs 80$ ; oops mov r0 ,r1 ; copy the parsed unit number .mtset #rtwork,#ttparm,r1 ; get the current settings bcc 20$ ; it worked cmpb @#errbyt,#1 ; not attached? bne 90$ ; no .mtatch #rtwork,#0,r1 ; yes, attach it bcs 90$ ; oops mov sp ,r2 ; flag we just attached it .mtset #rtwork,#ttparm,r1 ; get the current settings bcs 90$ ; error 20$: clr r0 ; success br 100$ ; bye 80$: mov #er$dev ,r0 ; bad device name br 100$ ; bye 90$: $mterr ; error, map into global and exit 100$: tst r2 ; need to detach it again beq 110$ ; no .mtdtch #rtwork,r1 ; yes, do it please 110$: unsave ; pop this and exit return .sbttl binrea read binary ; B I N R E A ; ; input: @r5 LUN ; 2(r5) timeout ; output: r0 error code ; r1 character just read m.xbinre:: m.binrea:: save ; we may want to use these here clr -(sp) ; allocate a single character buffer mov sp ,r4 ; and a pointer to it also clr -(sp) ; allocate a mark time tim buffer clr -(sp) ; simple mov sp ,r2 ; and point to it mov @r5 ,r3 ; get the LUN asl r3 ; and map it into the unit number movb lunmap(r3),r3 ; simple ;- .mtget #rtwork,#ttsts,r3 ; get current terminal setting ;- bcs 90$ ; oops ;- bis #ttmode ,ttsts+m.tsts ; set so we don't wait for anything ;- .mtset #rtwork,#ttsts,r3 ; set this please ;- bcs 90$ ; can't set it for some reason cmp 2(r5) ,#-1 ; read without any wait ? bne 40$ ; no .mtin #rtwork,r4,r3,#1 ; read a single character now bcs 80$ ; it worked clr r1 ; get the character into r1 now bisb @r4 ,r1 ; and exit with success clr r0 ; bye br 100$ ; exit at last 40$: mov 2(r5) ,r1 ; get the timeout in seconds mul #60. ,r1 ; into ticks now 50$: .mtin #rtwork,r4,r3,#1 ; do it please bcc 60$ ; it worked, get the ch into r1 dec r1 ; been here too long ? beq 80$ ; yes, exit with error tst clkflg ; /37/ is there a clock on system? bne 55$ ; /37/ yes cpuwait #1 ; /37/ no, try loop for one tick br 56$ ; /37/ very cpu speed dependent. 55$: .twait #rtwork,#ttime ; sleep a moment please 56$: br 50$ ; and try again please 60$: clr r1 ; it worked, get the character and exit bisb @r4 ,r1 ; simple clr r0 ; success br 100$ 80$: mov #er$nin ,r0 ; no data today br 100$ ; bye 90$: $mterr ; map the error code into a global one 100$: add #6 ,sp ; pop local buffers unsave ; pop registers and exit return 200$: mov #1 ,r1 ; flag a timeout return .sbttl binary write ; B I N W R I ; ; binwri( %loc buffer, %val buffer_size, %val lun ) ; ; output: r0 error code ; ; Assumption: TTYINI has been called to map the Kermit LUN ; into the RT11 unit number for the terminal. m.binwri:: save ; save registers we may need sub #20 ,sp ; a save area for tt settings clr r0 ; preset no errors as of yet mov @r5 ,r1 ; get the string address mov 2(r5) ,r2 ; get the string length beq 100$ ; nothing to do mov #ttsts ,r3 ; for getting tt settings mov 4(r5) ,r4 ; the internal LUN bne 10$ ; map LUN 0 to console print r1,r2 ; simple clr r0 ; no errors br 100$ ; exit 10$: mov sp ,r5 ; point to the stack work area asl r4 ; times two tstb lunmap+1(r4) ; have we mapped the lun into unit? beq 80$ ; no, fatal error movb lunmap(r4),r4 ; map into the rt11 unit number .mtget #rtwork,r3,r4 ; get current settings, set to wait bcs 90$ ; oops, exit with the error code in r0 mov (r3)+ ,(r5)+ ; copy the four words now mov (r3)+ ,(r5)+ ; copy the four words now mov (r3)+ ,(r5)+ ; copy the four words now mov (r3)+ ,(r5)+ ; copy the four words now bit #100 ,ttsts+m.tsts ; is the wait bit set already ? beq 20$ ; no, don't bother to clear it bic #100 ,ttsts+m.tsts ; set so we will wait for buffer space .mtset #rtwork,#ttsts,r4 ; simple to set 20$: .mtout #rtwork,r1,r4,r2 ; do the output now bcs 90$ ; oops, it failed for whatever reason mov -(r5) ,-(r3) ; restore the terminal settings mov -(r5) ,-(r3) ; restore the terminal settings mov -(r5) ,-(r3) ; restore the terminal settings mov -(r5) ,-(r3) ; restore the terminal settings .mtset #rtwork,r3,r4 ; simple clr r0 ; say it worked and exit br 100$ ; bye 80$: mov #er$map ,r0 ; rt11 unit not mapped to internal LUN br 100$ ; bye 90$: $mterr ; map mt error into global error code 100$: add #20 ,sp ; pop local work buffer unsave ; pop the saved registers return ; and exit .sbttl parse terminal unit ; T T P A R S ; ; input: @r5 address of RT11 Multiple terminal service unit string ; output: r0 unit in binary m.ttpars:: mov r1 ,-(sp) ; save scratch register please mov @r5 ,r0 ; get the address of the string call 200$ ; check for legit character bcs 110$ ; oops movb (r0)+ ,r1 ; get the first byte please sub #'0 ,r1 ; convert to binary call 200$ ; check for legit character bcs 110$ ; oops movb @r0 ,r0 ; get the next digit beq 100$ ; nothing there then we are done mul #12 ,r1 ; something there, shift over by 10 sub #'0 ,r0 ; and convert low digit to binary add r0 ,r1 ; add into the accumulator 100$: mov r1 ,r0 ; and return the result clc ; return success 110$: mov (sp)+ ,r1 return 200$: tstb @r0 ; null ? beq 210$ ; yes, it's ok cmpb @r0 ,#'0 ; must only be digits today blo 220$ ; oops cmpb @r0 ,#'9 ; 0..9 bhi 220$ ; bad device name 210$: clc ; device name ok so far return ; bye 220$: sec ; bad, set and exit return .sbttl GTTNAM get MT unit of current console (set tt:consol=nn) ; G T T N A M ; ; input: @r5 address of console name to be written ; output: @r5 current console name ; consave same thing .mcall .mtstat ; data returned by .mtstat ; ; offset 0 offset from RMON base to first TCB ; 2 offset from RMON base to the current console TCB ; 4 numer of luns generated into the exec ; 6 size of the TCB in bytes ; ; Since the TCB does NOT contain a copy of the LUN in it, we have ; to start with TCB number 0 and add in the TCB size until we get ; the value of the offset to the current console's TCB. Counting ; this will give us the LUN for that TCB. m.gttnam:: save ; save registers please .mtstat #rtwork,#mtsts ; get info on mt service clr r3 ; current lun number, starts with zero tst mtsts+4 ; see if mt service is present? beq 30$ ; no, ignore it for now mov mtsts+0 ,r1 ; offset to tcb for console interface mov mtsts+4 ,r2 ; number of tcb's generated in exec 10$: cmp r1 ,mtsts+2 ; find our tcb yet? beq 20$ ; yes, exit inc r3 ; no, then lun := succ(lun) add mtsts+6 ,r1 ; add the tcb size in and compage offset dec r2 ; if more tcbs to do, then try again bne 10$ ; next please 20$: 30$: asl r3 ; get word indexing please to map the add #200$ ,r3 ; value into a ascii string. mov @r5 ,r1 ; where to put it please movb (r3)+ ,@r1 ; copy a byte cmpb @r1 ,#40 ; but if it's a blank, then skip it beq 40$ ; a space inc r1 ; not a space, bump the dest pointer 40$: movb (r3)+ ,(r1)+ ; copy the next character now clrb @r1 ; always make it .asciz mov @r5 ,r1 ; copy to consave: mov #consave,r2 ; 50$: movb (r1)+ ,(r2)+ ; simple to copy .asciz string bne 50$ ; next please 100$: clr r0 unsave return ; This is a rather dumb way to convert to ascii, but there are only ; a few values, and it is easier to test via downloading to my PDT ; with Kermit since the PDT150 lacks DIV. 200$: .asciz / 0 1 2 3 4 5 6 7 8 9/ .asciz /101112131415161718/ .even global m.ttyfin:: call ttpars ; finish up mt service mov r0 ,r1 ; parse the device name .mtdtch #rtwork,r1 ; and detach the device now clr r0 ; return 'success' return ; and exit .sbttl speed read and change m.setspd:: save ; save temps that we will use clr r0 ; find the speed map now 10$: tst spdlst(r0) ; reach the end of the table? beq 80$ ; yes, return unknown speed cmp 2(r5) ,spdlst(r0) ; table entry match the passed speed beq 20$ ; yes add #2 ,r0 ; no, try the next one please br 10$ ; next please 20$: mov spdmap(r0),r3 ; and get the speed setting bits call ttpars ; parse the mt unit number bcs 70$ ; oops mov r0 ,r1 ; save the unit number .mtatch #rtwork,#kbiost,r1 ; insure unit is attached mov #ttsts ,r2 ; point to the status area .mtget #rtwork,r2,r1 ; get the current terminal setting bcs 90$ ; oops bic #7400 ,m.tsts(r2) ; clear out old speed bits bis r3 ,m.tsts(r2) ; stuff the dz11 speed bits in .mtset #rtwork,r2,r1 ; set these please bcs 90$ ; oops clr r0 ; all done br 100$ ; bye 70$: mov #er$dev ,r0 ; device name parse failed br 100$ ; bye 80$: mov #er$spe ,r0 ; unknown speed ? br 100$ 90$: $mterr ; map local error into a global one 100$: unsave ; pop and exit return m.ttspee:: save ; save these please call ttpars ; parse the mt unit number bcs 70$ ; oops mov r0 ,r1 ; save the unit number .mtatch #rtwork,#kbiost,r1 ; insure unit is attached mov #ttsts ,r2 ; point to the status area .mtget #rtwork,r2,r1 ; get the current terminal setting bcs 90$ ; oops mov m.tsts(r2),r3 ; get the speed mask out now bic #^C7400 ,r3 ; drop all bits but the speed clr r0 ; now look for the correct speed map 10$: tst spdmap(r0) ; reach the end of the list ? bmi 80$ ; yes, return a speed of zero cmp r3 ,spdmap(r0) ; setting match up now ? beq 20$ ; yes add #2 ,r0 ; no, try again please br 10$ ; next 20$: mov spdlst(r0),r0 ; a match, return the speed setting br 100$ ; bye 70$: mov #er$dev ,r0 ; device name parse failed br 100$ ; bye 80$: clr r0 ; failure br 100$ ; return a speed of zero then 90$: $mterr ; map local error into a global one 100$: unsave ; pop and exit return .save .psect $pdata spdlst: .word 50. ,75. ,110. ,134. ,150. ,300. ,600. .word 1200. ,1800. ,2000. ,2400. ,3600. ,4800. ,7200. .word 9600. ,0 ,0 spdmap: .word 0 ,400 ,1000 ,1400 ,2000 ,2400 ,3000 .word 3400 ,4000 ,4400 ,5000 ,5400 ,6000 ,6400 .word 7000 ,7400 ,-1 .restore .sbttl terminal i/o things we don't need, can't do or haven't done yet m.ttxon:: m.cantyp:: m.ttset:: m.ttydtr:: m.ttrfin:: m.ttrini:: clr r0 return m.ttyhan:: mov #er$iop ,r0 return .mcall .ttyin jsw = 44 m.kbread:: mov r2 ,-(sp) mov r3 ,-(sp) bis #40000 ,@#jsw ; enable lower case tt: input bic #10000 ,@#jsw ; ditch single ch input please mov @r5 ,r1 ; a buffer to put the chars mov #80. ,r3 ; size of the buffer here ;10$: .scca #area ,#kmonbf ; so we can catch control Z 10$: .ttyin ; read a character please tstb r0 beq 15$ ; a null cmpb r0 ,#'Z&37 ; control Z ? beq 20$ ; yes cmpb r0 ,#'C&37 ; control C ? beq 20$ ; yep cmpb r0 ,#15 ; carriage return ? beq 30$ ; yep movb r0 ,(r1)+ ; return what we just got cmpb r0 ,#14 ; form feed ? beq 40$ ; yep 15$: sob r3 ,10$ ; next please 20$: mov #er$eof ,r0 ; say read error and exit br 100$ ; bye 30$: movb #cr ,(r1)+ ; return all terminators please movb #lf ,(r1)+ ; simple .ttyin ; eat the line feed now 40$: clrb @r1 sub @r5 ,r1 ; the length clr r0 100$: mov (sp)+ ,r3 mov (sp)+ ,r2 return m.finrt:: ; /37/ clr r0 ; /37/ return ; /37/ m.senbrk:: calls ttspee ,<@r5> ; get the remotes terminal speed mov r0 ,r2 ; save the old speed calls setspd ,<@r5,#50.,2(r5)>;try to set it down to 50 baud tst r0 ; did it work ? bne 100$ ; no, forget it calls binwri ,<#200$,#2,2(r5)>;yes, send a null over calls setspd ,<@r5,r2,2(r5)> ; restore the terminal's speed 100$: clr r0 return 200$: .byte 0,0 .end