.title Serial Line unit handler ; DECUS C Calling Format ; ; jsr r5,csv$ ;save r2,r3, and r4 ; ;r5 is parameter base ; ;c$pmtr(r5) is first argument ; ;c$pmtr+2(r5) is second argument ; ;... ; ;return args in r0 ; ... ; user code ; ... ; ; jmp cret$ ;restore r2-r5 and return ; rts pc ;does the same (cret$ follows csv$) ; ; csv$ and cret$ need be used only if arguments are used ; .include "os.mac" .mcall .close arg1 = 2 .if ne ts$sys ;tsx-plus specific CLIUNT = 13 ;Channel # for CL unit input CLOUNT = 12 ;Channel # for CL unit output CLCTRL = 11 ;Channel # for CL unit control CLRXNF = 201 ;SPFUN code to clear XOFF / send XON CLRBYT = 203 ;SPFUN code to read CL with byte count CLSOPT = 250 ;SPFUN code to set CL options CLCOPT = 251 ;SPFUN code to clear CL options CLABRT = 257 ;SPFUN code to abort this jobs pending i/o CLIPND = 261 ;SPFUN code to get # chars pending CL input CLWBYT = 263 ;SPFUN code to write CL with byte count CLRST = 265 ;SPFUN code to reset CL unit .sbttl CL Unit Initialization .psect c$code sl.init:: mov #-1,-(sp) ;error return mov arg1+2(sp),r0 ;get unit number cmp r0,#7 bhi 1$ mov #^rCL0,clspec ;restore spec add r0,clspec ;compute unit jsr pc,sl.abort ;abort any current i/o mov #lkaloc,r0 ;allocate CL unit emt 375 bcs 1$ ;allocation error - exit mov #lkctla,r0 ;.lookup emt 375 bcs 1$ ;device error - exit mov #lkinpa,r0 ;.lookup emt 375 bcs 1$ ;device error - exit mov #lkoupa,r0 ;.lookup emt 375 bcs 1$ ;device error - exit mov #clrset,r0 ;.spfun emt 375 bcs 1$ ;initialization error - exit mov #clset,r0 ;.spfun emt 375 bcs 1$ ;initialization error - exit mov #clclr,r0 ;.spfun emt 375 bcs 1$ ;initialization error - exit clr oupact ;clear output jsr pc,$mrkto ;startup CL input timeout clr (sp) 1$: mov (sp)+,r0 rts pc .psect c$data lkaloc: .byte 0,156 ;allocate CL unit .word clspec lkctla: .byte CLCTRL,1 ;lookup .word clspec .word 0 lkinpa: .byte CLIUNT,1 ;lookup .word clspec .word 0 lkoupa: .byte CLOUNT,1 ;lookup .word clspec .word 0 clspec: .rad50 /CL0/ ;cl unit specification .word 0,0,0 clrset: .byte CLCTRL,32 ;.spfun for CLRST .word 0 .word 0 .word 0 .byte 377,CLRST .word 0 ; CL unit flags, (1) set, (0) noset ;000001 FORM Send form feed characters ;000002 TAB Send tab characters ;000004 LC Send lower case letters ;000010 LFOUT Send line feed characters ;000020 LFIN Accept line feed characters ;000040 FORM0 Send form feed on block 0 write ;000100 BINOUT Send binary output characters ;000200 BININ Accept binary input characters ;000400 CR Send carriage return characters ;001000 CTRL Send control characters ;002000 DTR Raise Data Terminal Ready (DTR) ;004000 EIGHTBIT Accept and send 8 bit characters clset: .byte CLCTRL,32 ;.spfun for CLSOPT .word 0 .word 1$ .word 0 .byte 377,CLSOPT .word 0 1$: .word 001437 ;set these flags clclr: .byte CLCTRL,32 ;.spfun for CLCOPT .word 0 .word 1$ .word 0 .byte 377,CLCOPT .word 0 1$: .word 006340 ;clear these flags .sbttl CL Unit Abort I/O .psect c$code sl.abort:: mov #clabt,r0 ;abort i/o emt 375 mov #$cmkta,r0 ;abort .mrkt request emt 375 .close #CLCTRL ;close the channel .close #CLIUNT ;close the channel .close #CLOUNT ;close the channel rts pc .psect c$data clabt: .byte CLCTRL,32 ;.spfun for CLABRT .word 0 .word 0 .word 0 .byte 377,CLABRT .word 0 .page .sbttl CL Input a String ; bytes = sl_gets(buffer, maxbytes); .psect c$code sl.gets:: jsr r5,csv$ clr -(sp) ;null character count clr slbyts mov #slgcnt,r0 ;any pending characters ? emt 375 mov slbyts,r2 ;if no characters - finished beq 2$ mov c$pmtr(r5),slbufr ;buffer address mov c$pmtr+2(r5),r1 ;buffer length beq 2$ ;bad argument (=0) cmp r1,r2 ;select smallest of blos 1$ ;slbyts or maxbytes mov r2,r1 1$: mov r1,slbyts ;characters to read mov r1,(sp) ;characters returned mov #slgstr,r0 ;place characters in buffer emt 375 clr ticks ;character received 2$: mov (sp)+,r0 ;return a NULL / CHARACTER COUNT rts pc slgcnt: .byte CLIUNT,32 ;.spfun for CLIPND .word 0 .word slbyts .word 0 .byte 377,CLIPND .word 0 slgstr: .byte CLIUNT,32 ;.spfun for CLRBYT .word 1 slbufr: .word 0 slbyts: .word 0 .byte 377,CLRBYT .word 0 .page .sbttl CL Input Timeout .psect c$code $mrkto: add $mrktm,ticks ;update ticks cmp #60.*60.,ticks ;line timeout ? bhi 1$ ;no - skip clr ticks ;yes - clear ticks mov #clrhnd,r0 ;yes - clear XOFF / send XON emt 375 1$: mov #$mrkta,r0 ;set up next time interrupt emt 375 ;.mrkt request rts pc .psect c$data ticks: .word 0 ;clock ticks clrhnd: .byte CLCTRL,32 ;.spfun for CLRXNF .word 0 .word 0 .word 0 .byte 377,CLRXNF .word 0 $mrkta: .byte 0,22 ;.mrkt emt .word 1$ ;time to wait address .word $mrkto ;entry point .word 3 ;id = 3 1$: .word 0 $mrktm: .word 60 ;1 second $cmkta: .byte 0,23 ;.cmkt .word 3 ;id = 3 .word 0 .page .sbttl CL Output .psect c$code sl.putc:: tst oupact ;active ? bne 1$ ;yes - exit mov #1,oupact ;active movb arg1(sp),chroup ;place character mov #clpchr,r0 ;send character emt 375 mov arg1(sp),r0 ;character rts pc 1$: mov #-1,r0 ;EOF rts pc cloupc: clr oupact ;finished rts pc .psect c$data oupact: .word 0 ;active flag clpchr: .byte CLOUNT,32 ;.spfun for CLWBYT .word 1 .word chroup clocnt: .word 1 .byte 377,CLWBYT .word cloupc chroup: .word 0 ;output character .endc .if ne rt$sys ;rt-11 specific .sbttl MultiTerminal Unit Initialization .psect c$code sl.init:: mov #-1,-(sp) ;error return mov arg1+2(sp),r0 ;get unit number cmp r0,#7 bhi 1$ movb r0,mtatch+4 ;set unit numbers movb r0,mtget+4 movb r0,mtset+4 movb r0,mtrcto+4 movb r0,mtdtch+4 movb r0,mtin+4 movb r0,mtout+4 movb r0,mtxon+4 movb r0,mtxoff+4 mov #mtatch,r0 ;.mtatch emt 375 bcs 1$ mov #mtget,r0 ;.mtget emt 375 bcs 1$ bis #150305,m.tsts ;100000 (15) use backspace for rubout bic #020072,m.tsts ;040000 (14) lower to upper disabled ;020000 (13) terminal is remote ;010000 (12) character mode input ;007400 (11-8) terminal line speed ;000200 (7) enable ^S - ^Q processing ;000100 (6) inhibit TT wait ;000010 (3) process ^X, ^F and ^B ;000004 (2) Terminal has form feed ;000002 (1) output RET/LF on too wide ;000001 (0) terminal has tab bis #100200,m.tst2 ;100000 (15) write all ;077400 (14-8) reserved ;000200 (7) read all ;000140 (6-5) reserved ;000020 (4) DZ, odd parity ;000010 (3) DZ, enable parity ;000004 (2) DZ, 2 stop bits ;000003 (1-0) DZ, 5(00), 6(01), ; char bits 7(10), 8(11) ; m.tstw --- ;100000 (15) Acting console ;040000 (14) double ^C struck ;020000 (13) read all ;010000 (12) DZ11 ;004000 (11) terminal has hung ;002000 (10) terminal is shared mov #mtset,r0 ;.mtset emt 375 bcs 1$ mov #mtrcto,r0 ;.mtrcto emt 375 bcs 1$ jsr pc,$mrkti ;.mtin clr (sp) 1$: mov (sp)+,r0 rts pc .psect c$data mtatch: .byte 5,37 ;attach a terminal unit .word m.asts ;address of asynchronous status word .word 0 ;unit mtget: .byte 1,37 ;get status of terminal unit .word m.tsts .word 0 ;unit mtset: .byte 0,37 ;set status of terminal unit .word m.tsts .word 0 ;unit mtrcto: .byte 4,37 ;get status of terminal unit .word 0 .word 0 ;unit m.asts: .word 040000 ;asynchronous terminal status ;If the asynchronous terminal ;status is not included during ;system generation then this ;bit always stays SET m.tsts: .word 0 ;terminal configuration word 1 m.tst2: .word 0 ;terminal configuration word 2 m.tfil: .byte 0 ;character requiring fillers m.fcnt: .byte 0 ;number of fillers m.twid: .byte 0 ;carriage width m.tstw: .byte 0 ;terminal status byte .sbttl MultiTerminal Unit Abort I/O .psect c$code sl.abort:: mov #mtdtch,r0 ;abort i/o emt 375 mov #$cmkta,r0 ;abort .mrkt request emt 375 rts pc .psect c$data mtdtch: .byte 6,37 ;.mtdtch .word 0 .word 0 ;unit .page .sbttl MultiTerminal Input a String ; bytes = sl_gets(buffer, maxbytes); .psect c$code sl.gets:: jsr r5,csv$ clr r0 ;null character count mov c$pmtr(r5),r3 ;buffer address mov c$pmtr+2(r5),r2 ;character count beq 3$ mov outptr,r1 1$: cmp r1,inptr ;characters available ? beq 2$ movb getbuf(r1),(r3)+ ;take character incb r1 ;MOD 256. mov r1,outptr ;save index sob r2,1$ 2$: mov c$pmtr+2(r5),r0 ;compute number of sub r2,r0 ;characters returned beq 3$ clr ticks ;characters received 3$: rts pc ;return a NULL / CHARACTER COUNT .page .sbttl Asynchronous MultiTerminal Character Processing .psect c$code $mrkte: jsr pc,mtchar ;check for characters mov inptr,r1 ;compute characters in buffer sub outptr,r1 bic #^C377,r1 ;MOD 256. bne 2$ cmp #60.*60.,ticks ;line timeout ? blos 1$ ;XON at timeout tst xoffed ;XON at empty buffer beq 2$ 1$: mov #mtxon,r0 emt 375 bcs 2$ clr xoffed clr ticks 2$: cmp r1,#192. blt $mrkti tst xoffed ;XOFF at almost full buffer bne 3$ mov #mtxoff,r0 emt 375 bcs 3$ inc xoffed 3$: jsr pc,resume ;incoming characters $mrkti: mov #$mrkta,r0 ;set up next time interrupt emt 375 ;.mrkt request rts pc mtchar: add $mrktm,ticks ;clock ticks jsr pc,1$ beq 5$ clr ticks ;clear timeout ticks 1$: clr -(sp) ;no characters bit #40000,m.asts ;characters available ? beq 4$ ;no - exit mov #255.,r1 ;limit mov inptr,r0 ;compute characters in buffer sub outptr,r0 bic #^C377,r0 ;MOD 256. sub r0,r1 ;space available beq 4$ mov #256.,r0 ;space to end of buffer sub inptr,r0 cmp r1,r0 ;use smaller ble 2$ mov r0,r1 2$: mov #mtin,r0 ;.mtin movb r1,5(r0) ;character count mov #getbuf,r1 ;buffer address add inptr,r1 mov r1,2(r0) emt 375 bcc 3$ tstb @#52 ;assume error is data not available bne 4$ ;real error 3$: mov r0,(sp) ;compute number of sub r1,(sp) ;characters returned beq 4$ mov (sp),r0 add inptr,r0 ;update index movb r0,inptr ;MOD 256. 4$: mov (sp)+,r0 ;return a NULL / CHARACTER COUNT 5$: rts pc .psect c$data $cmkta: .byte 0,23 ;.cmkt .word 3 ;id = 3 .word 0 $mrkta: .byte 0,22 ;.mrkt emt .word 1$ ;time to wait address .word $mrkte ;entry point .word 3 ;id = 3 1$: .word 0 $mrktm: .word 3 ;1/20 th of a second mtin: .byte 2,37 ;.mtin .word 0 .byte 0,0 mtxon: .byte 3,37 ;.mtout xon .word 1$ .byte 0,1 1$: .word 21 ;XON mtxoff: .byte 3,37 ;.mtout xoff .word 1$ .byte 0,1 1$: .word 23 ;XOFF xoffed: .word 0 ;xoffed flag ticks: .word 0 ;elapsed ticks outptr: .word 0 ;output index inptr: .word 0 ;input index getbuf: .blkb 256. ;buffer area .page .sbttl MultiTerminal Output .psect c$code sl.putc:: mov #-1,r1 ;EOF movb arg1(sp),chroup ;place character mov #mtout,r0 ;send character emt 375 bcs 1$ mov chroup,r1 1$: mov r1,r0 ;character / EOF rts pc .psect c$data mtout: .byte 3,37 ;.mtout .word chroup .byte 0,1 chroup: .word 0 ;character .endc .end