.title K11DIA dial command for kermit-11 .ident /t2.40/ ; 18-Oct-85 20:06:09 Brian Nelson ; ; 04-Dec-85 11:22:32 BDN Add optional linked list structure to ; define modem responses, will be useful ; when adding a SET DIAL command. ; 06-Dec-85 11:53:59 BDN Added extra field in DEFINE macro and ; support code to call external routines ; for dialing, needed for PRO/TMS. ; 09-Jan-86 17:48:17 RTM Added support for the RIXON Intelligent ; (RTM01) autodial modem (R212A). ; ; 13-Feb-86 10:10:08 BDN Put the DF112 and DF224 responses into ; linked lists. ; 23-Sep-86 14:10:30 BDN Vadic 4224 modems ; 23-Sep-86 14:10:42 BDN Added format effector %M for pulse/tone ; if a SET PHONE PULSE/TONE was done. Also ; added %B for 'blind' dialing, enabled if ; SET PHONE BLIND ; 30-Sep-86 13:05:53 BDN Added CTS2424, Also SHO DIAL ; 09-Feb-89 00:00:00 JCH Complete definition of DF224 modem. ; ; Copyright (C) 1985 1986 Change Software, Inc. ; ; ; Its about time for a DIAL command. Would be really nice to use ; on my PRO/350 and the XK: port. Of limitted utility on the 44 ; as I have to enter the GANDALF PACX to access the VADIC 212PAR ; modems. ; ; As noted in a number of comments, the timer support for RSTS/E ; is abbysmal, the only thing you can do is SLEEP n, where 'n' is ; in seconds. Even worse is the fact that various asynchronous ; events can prematurely cancel the sleep, like a delimiter typed ; at a terminal allocated to the job. Also, you can NOT do a mark ; time on RSTS/E, though version 9 does have the groundwork layed ; for adding timer AST's in that v9 supports asych i/o, thus the ; needed executive data structures are mostly present. ; ; I do not mean to knock RSTS/E really, RSTS has a great number ; of features that make interfacing with the terminal driver much ; simpler than what one finds on RSX and RT11, while at the same ; time introducing its own peculiarities. RSX is by far the worst ; as I often find grossly dissimiliar behavior between RSX sites. ; ; As a final reflection, if I were to grade RSTS, RT and RSX on ; simplicity and stability of terminal driver interfacing, RT11 ; would have to come first (both MT and XC/XL versions), followed ; by RSTS and bringing up the rear, RSX (I've been burned on both ; RSX and RSTS when new versions came out, though being a RSTS/E ; field test site tends to help). .if ndf, K11INC .ift .include /IN:K11MAC.MAC/ .endc .enabl lc .nlist ; It would be nice to be able to do this in a macro call but the ; PDP-11 assembler does not allow continuation lines. So what we ; will instead do is define each arg as a word offset from a base ; address of a list for that modem. ; In many cases we could fit all the info on one line, but macros ; dragged out that way are unreadable. It would be really nice to ; be able to say: ; ; moddef type = - , ; dial.time = 30. - , ; wake.string = ..... and so on. ; ; .macro moddef dial.t,wake.s,wake.r,wake.p,dmod.s,dmod.p,dial.s,dial.r ; ; Losely based on CKUDIAL.C ; ; All times for delays are in TICKS (1/60 second intervals) ; ; dial.time Time the modem may use to dial a number ; wake.string Get modems attention, like in VADIC 212 ^E ; wake.rate Delay in milliseconds modem may need ; wake.prompt Modems command mode prompt ; dmod.string String needed to get it to dial a number ; dmod.prompt Dial mode prompt ; dial.string The string for dial, includes a %s for number position ; dial.rate delay between sending numbers over, in TICKS ; wake.ack as in va212, 'HELLO:I'M READY' ; dial.ack string to wait for to confirm number ; dial.echo ; ; WARNING: If any of these values are CHANGED, and there is absolutely ; NO reason to do so, you must check K11ST0.MAC where a few of these ; are also defined for the SET DIAL command. Anything new that's need- ; ed in the modem database is always added on to the END of the list. ; While it is freely acknowledged that there are now a couple of ob- ; solete fields, it doesn't cost that much. Leave the structure alone. mod.next =: 0 ; next modem in list mod.str =: 2 ; address of name of modem mod.val =: 4 ; numeric value for dispatching dial.time =: 6 ; value of dial time wake.string =: 10 ; address of wakeup string wake.rate =: 12 ; value of delay wake.prompt =: 14 ; address of wakeup prompt dmod.string =: 16 ; address of dial dial string dmod.prompt =: 20 ; address of prompt returned for dial dial.string =: 22 ; address of formatting string for dial dial.rate =: 24 ; value of delay wake.ack =: 26 ; address of wakeup response dial.ack =: 30 ; 1st = waitfor, 2nd to confirm number dial.online =: 32 ; online ack string dial.blind =: 34 ; blind ack dial.wait =: 36 ; String for PAUSE characters dial.confirm =: 40 ; string to confirm number for dialing dial.go =: 42 ; ie, va212 returns "DIALING\n" res.bin =: 44 ; if <>, returns status with \n ; otherwise a binary response (DF03) dial.echo =: 46 ; if <>, numbers are echoed immediately mod.comment =: 50 ; res.head =: 52 ; ext.dial =: 54 ; if ne, address of external dialer dial.xabort =: 56 ; /45/ To abort call from modem dial.idle =: 60 ; /45/ Place modem in IDLE state dial.pulse =: 62 ; /45/ Switch to pulse dialing dial.nopulse =: 64 ; /45/ Switch to tone dialing def.guard =: 66 ; /45/ last thing (unused) .psect modinf ,ro,d,lcl,rel,con .enabl lc .macro modval val,offset .save .psect modinf . = $$current + offset .word val .restore .endm modval .macro modstr s,offset .save .psect string $$addr = . $$ = 0 .irpc ch, ch1 = ''ch .if eq, ch1 - '^ .ift $$ = 100 .iff .if ne ,$$ .if ge , - <'a!40> .iif le, - <'z!40>, ch1 = ch1&137 .endc .endc .byte ch1-$$ $$ = 0 .endc .endr .byte 0 .restore .save .psect modinf . = $$current + offset .word $$addr .restore .endm modstr .sbttl inialize subfields of modem info structure .macro dial$time val modval val,dial.time .endm dial$time .macro wake$rate val modval val,wake.rate .endm wake$rate .macro dial$rate val modval val,dial.rate .endm dial$rate .macro wake$string s modstr ,wake.string .endm wake$string .macro wake$prompt s modstr ,wake.prompt .endm wake$prompt .macro dmod$string s modstr ,dmod.string .endm dmod$string .macro dmod$prompt s modstr ,dmod.prompt .endm dmod$prompt .macro dial$string s modstr ,dial.string .endm dial$string .macro mod$comment s modstr ,mod.com .endm mod$comment .macro dial$ack s modstr ,dial.ack .endm dial$ack .macro dial$confirm s modstr ,dial.confirm .endm dial$confirm .macro dial$online s modstr ,dial.online .endm dial$online .macro dial$blind s modstr ,dial.blind .endm dial$blind .macro dial$wait s modstr ,dial.wait .endm dial$wait .macro dial$go s modstr ,dial.go .endm dial$go .macro dial$echo v modval v,dial.echo .endm dial$echo .macro dial$pulse s ; /45/ String to force PULSE dialing modstr ,dial.pulse ; /45/ ... .endm dial$pulse ; /45/ ... .macro dial$nopulse s ; /45/ String to force tone dialing modstr ,dial.nopulse ; /45/ ... .endm dial$nopulse ; /45/ ... .macro dial$xabort s ; /45/ Use this field if we detect modstr ,dial.xabort ; /45/ a control C abort and need .endm dial$xabort ; /45/ to get the modem to stop dialing .macro dial$idle s ; /45/ Switch from command mode to modstr ,dial.idle ; /45/ to IDLE mode .endm dial$idle ; /45/ .macro ext$dial v modval v,ext.dial .endm ext$dial .macro res$bin v modval v,res.bin .endm res$bin .macro wake$ack s modstr ,wake.ack .endm wake$ack $$prev = modinf $$seq = 1 .save .psect usermd ,rw,d,gbl,rel,con null2: .byte 0 null: .byte 0 .psect string ,ro,d,lcl,rel,con .psect rwdata ,rw,d,lcl,rel,con bell: .byte 'G&37,'G&37,0 .even modtyp: .word 0 buffer: .blkb 200 ttbuff: .blkb 200 .restore .macro define lab ,s ,user .if nb ,user ; if we are defining the 'user' .ift ; modem we need to be in a global .save ; psect to be located in the root .psect usermd ,rw,d,gbl,rel,con ; put a reference to this psect .iff ; in k11dat $modtail== . ; to manually set link to 'usermd' .endc ; .iif ndf, $$prev ,$$prev = modinf $$current = . ; save current pc $res = 0 $reslast= 0 lab: .word 0 ; link to next please .iif nb, user, .globl lab ; must be global if USER mode .save ; save current psect .psect string ; switch to string psect $$ = . ; save it's current PC .asciz /s/ ; insert the modem type string .even ; always useful for word addressing .restore ; pop the previous psect (modinf) .word $$ ; and insert address of the string $'lab = $$seq ; define sequence value .word $$seq ; store value in structure $$seq = $$seq + 1 ; sequence number .word 30. ; default for dial time .word null ; default for wakeup .word 0 ; default for delay .word null ; default for command mode prompt .word null ; default for dial command .word null ; default for dial prompt .word null ; default for dial formatting .word 0 ; default for dial delay .word null ; default for wakeup ack .word null2 ; default for ack string .word null ; default for dial.online .word null ; default for dial.blind .word null ; default for dial.wait .word null ; default for dial.confirm .word null ; default for dial.go .word 0 ; 0 normal, else 1 for binary (res.bin) .word 0 ; default for dial.echo .word null ; default for MOD$COMMENT .word 0 ; res.head .word 0 ; possible external dialer address .word null ; /45/ Default for XABORT string .word null ; /45/ Default for IDLE string .word null ; /45/ Default for PULSE dialing .word null ; /45/ Default for TONE dialing .word 0 ; guard word $$end = . $$size = $$end - $$current .assume $$size eq .if b ,user ; we don't want psect errors from .ift ; MAC for the USER modem type. . = $$prev .word lab . = $$end $$prev = lab .iff .restore ; for USER type, return to old psect .endc ; Also, the USER modem MUST be last .endm define .sbttl create a linked list, header in res.head ; Added edit /39/ Brian Nelson 4-DEC-1985 09:46 ; ; Create a linked list of possible modem responses. The ; advantages of this is that we could use a SET DIAL command ; to create a modem data structure at run time, and that ; defining modems is simplified. As a note, there is no ; requirement to use this structure. It will be used for the ; DEFAULT entry in the 'GETSTS' routine. ; ; ; Format is: res.head(current_modem) --> first entry ; ; ; Entry format: .word next (or zero for tail) ; .word class (-1 fail, 0 info, 1 sucess) ; .asciz /response_string/ CONNECT = 1 INFO = 0 FAILED = -1 .save .psect resdat ,rw,d,lcl,rel,con resdat: .restore .macro mod$res s,class .save ; save current psect context .psect resdat ,rw,d,lcl,rel,con $res1 = . ; save current pc in 'resdat' .word 0 ; link to next is zero .if b, class ; if class not specified, then .word 0 ; make it zero .iff ; else insert it .word class ; response class .endc ; if b, class .asciz /s/ ; the actual text .even ; must do .restore ; get last psect .if eq ,$res ; is this first time for new .ift ; type ? modval $res1,res.head ; yes, stuff the link header .iff ; not the first time .save ; save current psect context .psect resdat ; and a new one $respc = . ; save the current pc . = $reslast ; backup to link word from previous .word $res1 ; insert address of new entry . = $respc ; restore correct pc .restore ; restore old psect context .endc ; end $reslast = $res1 ; lastlink = current_entry $res = 1 ; not the first time anymore .endm ; thats it .list .sbttl finally, we can define the modem .psect modinf ,ro,d,lcl,rel,con ; All xxxx$rate values are in TICKS (1/60 second) ; WARNING: The definition for USER_DEFINED MUST be last !!!!!!! ; WARNING: Before accessing any data here from outside of this ; module (overlay), insure the overlay is loaded, as in calling ; FINDMODEM with the modem type string .asciz pointed to by R5. modinf:: define v2pa , ; stand alone VA212PA dial$time 35. wake$string <^E^M> wake$rate 10 ; wait 8 ticks (8/60 second) wake$ack wake$prompt <*> dmod$string dmod$prompt dial$string <%s^M> dial$rate 10 dial$ack <^M> dial$confirm <^M> dial$go dial$echo 1 dial$xabort <^M> dial$idle dial$wait mod$comment mod$res ,CONNECT mod$res ,CONNECT mod$res ,FAILED mod$res ,FAILED mod$res ,FAILED mod$res ,FAILED mod$res