home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
pdp11
/
k11dia.mac
< prev
next >
Wrap
Text File
|
2020-01-01
|
44KB
|
1,619 lines
.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 = <VA212PAR> - ,
; 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<CR>
; 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,<s>
ch1 = ''ch
.if eq, ch1 - '^
.ift
$$ = 100
.iff
.if ne ,$$
.if ge , <ch1!40> - <'a!40>
.iif le, <ch1!40> - <'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 <s>,wake.string
.endm wake$string
.macro wake$prompt s
modstr <s>,wake.prompt
.endm wake$prompt
.macro dmod$string s
modstr <s>,dmod.string
.endm dmod$string
.macro dmod$prompt s
modstr <s>,dmod.prompt
.endm dmod$prompt
.macro dial$string s
modstr <s>,dial.string
.endm dial$string
.macro mod$comment s
modstr <s>,mod.com
.endm mod$comment
.macro dial$ack s
modstr <s>,dial.ack
.endm dial$ack
.macro dial$confirm s
modstr <s>,dial.confirm
.endm dial$confirm
.macro dial$online s
modstr <s>,dial.online
.endm dial$online
.macro dial$blind s
modstr <s>,dial.blind
.endm dial$blind
.macro dial$wait s
modstr <s>,dial.wait
.endm dial$wait
.macro dial$go s
modstr <s>,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 <s>,dial.pulse ; /45/ ...
.endm dial$pulse ; /45/ ...
.macro dial$nopulse s ; /45/ String to force tone dialing
modstr <s>,dial.nopulse ; /45/ ...
.endm dial$nopulse ; /45/ ...
.macro dial$xabort s ; /45/ Use this field if we detect
modstr <s>,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 <s>,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 <s>,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 <def.guard+2>
.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 ,<VA212PA> ; stand alone VA212PA
dial$time 35.
wake$string <^E^M>
wake$rate 10 ; wait 8 ticks (8/60 second)
wake$ack <HELLO:I'M READY>
wake$prompt <*>
dmod$string <D^M>
dmod$prompt <?>
dial$string <%s^M>
dial$rate 10
dial$ack <^M>
dial$confirm <^M>
dial$go <DIALING>
dial$echo 1
dial$xabort <^M>
dial$idle <I^M>
dial$wait <K>
mod$comment <Stand alone VADIC VA212>
mod$res <ON LINE> ,CONNECT
mod$res <ONLINE> ,CONNECT
mod$res <BUSY> ,FAILED
mod$res <FAILED CALL> ,FAILED
mod$res <NO DIAL> ,FAILED
mod$res <VOICE> ,FAILED
mod$res <TIME OUT> ,FAILED
mod$res <RINGING> ,INFO
define v2par ,<VA212PAR> ; rack mounted VA212PAR
dial$time 35.
wake$string <^E^M>
wake$rate 10
wake$ack <HELLO:I'M READY>
wake$prompt <*>
dmod$string <D^M>
dmod$prompt <?>
dial$string <%s^M>
dial$rate 10
dial$go <DIALING>
dial$echo 1
dial$xabort <^M>
dial$idle <I^M>
dial$wait <K>
mod$comment <Rack mounted VADIC VA212PAR>
mod$res <ON LINE> ,CONNECT
mod$res <ONLINE> ,CONNECT
mod$res <BUSY> ,FAILED
mod$res <FAILED CALL> ,FAILED
mod$res <NO DIAL> ,FAILED
mod$res <VOICE> ,FAILED
mod$res <TIME OUT> ,FAILED
mod$res <RINGING> ,INFO
define vadic ,<VADIC> ; stand alone VA212PA
dial$time 35.
wake$string <^E^M>
wake$rate 10
wake$ack <HELLO:I'M READY>
wake$prompt <*>
dmod$string <D^M>
dmod$prompt <?>
dial$string <%s^M>
dial$rate 10
dial$ack <^M>
dial$confirm <^M>
dial$go <DIALING>
dial$echo 1
dial$xabort <^M>
dial$idle <I^M>
dial$wait <K>
mod$comment <Generic VADIC with autodial>
mod$res <ON LINE> ,CONNECT
mod$res <ONLINE> ,CONNECT
mod$res <BUSY> ,FAILED
mod$res <FAILED CALL> ,FAILED
mod$res <NO DIAL> ,FAILED
mod$res <VOICE> ,FAILED
mod$res <TIME OUT> ,FAILED
mod$res <RINGING> ,INFO
define cts24 ,<CTS2424> ; CTS (Fabritek) 2424 autodial
dial$time 35.
wake$string <^T^WAT^Q^M> ; Just in case add ^Q<cr> in also
wake$rate 10
wake$ack <Modem Ready>
dial$string <D%M%B%S^M>
dial$rate 10
dial$xabort <^T^W>
dial$idle <^T^W>
dial$wait <+>
dial$pulse <P>
dial$nopulse <T>
dial$blind <&>
dial$echo 1
mod$comment <CTS/Fabri-Tek 2424AD V.22bis Autodialier>
mod$res <Ring> ,INFO
mod$res <Busy> ,FAILED
mod$res <Dead Line> ,FAILED
mod$res <Disconnect> ,FAILED
mod$res <Modem Ready> ,INFO
mod$res <No Answer> ,FAILED
mod$res <No Dialtone> ,FAILED
mod$res <No Tone> ,FAILED
mod$res <On Line> ,CONNECT
mod$res <On Line Originate>,CONNECT
mod$res <Redialing> ,INFO
define va42 ,<VA4224> ; Rack mount 2400 baud
dial$time 35.
wake$string <^E^M>
wake$rate 10
wake$ack <HELLO:I'M READY>
wake$prompt <*>
dial$string <D%M%S%B^M>
dial$rate 10
dial$go <DIALING>
dial$echo 1
dial$xabort <^M>
dial$idle <I^M>
dial$wait <K>
dial$pulse <P>
dial$nopulse <T>
dial$blind <B>
mod$comment <Vadic 4224 CCITT V.22bis autodial>
mod$res <ON LINE> ,CONNECT
mod$res <ONLINE> ,CONNECT
mod$res <BUSY> ,FAILED
mod$res <FAILED CALL> ,FAILED
mod$res <NO DIAL> ,FAILED
mod$res <VOICE> ,FAILED
mod$res <TIME OUT> ,FAILED
mod$res <RINGING> ,INFO
mod$res <ON LINE 300> ,CONNECT
mod$res <ON LINE 1200> ,CONNECT
mod$res <ON LINE 2400> ,CONNECT
mod$res <ERROR CONTROL> ,INFO
mod$res <NO ERROR CONTROL>,INFO
define df03 ,<DF03> ; dec DF03
dial$time 30.
wake$string <^A^B>
dial$string <%s>
dial$echo 1
res$bin 1 ; responds in binary (no crlf)
mod$comment <DEC DF03AC Autodial modem>
define df100 ,<DF100> ; a DF112
dial$time 30.
wake$string <^B>
wake$rate 0
wake$ack <Ready>
wake$prompt <Ready>
dial$string <%s#> ; /45/
dial$rate 10
dial$xabort <^M>
dial$echo 1
mod$comment <DEC Standalone DF112>
mod$res <Attached> ,CONNECT
mod$res <Busy> ,FAILED
mod$res <Disconnected> ,FAILED
mod$res <Error> ,FAILED
mod$res <No answer> ,FAILED
mod$res <No dial tone> ,FAILED
mod$res <Speed:> ,FAILED
define df200 ,<DF200> ; a DF2xx ?
dial$time 30.
wake$string <^B>
wake$rate 0
wake$ack <Ready>
wake$prompt <Ready>
dial$string <%b%m%s!> ; /60/
dial$rate 0
dial$xabort <^B> ; /60/
dial$echo 1
dial$pulse <P> ; /60/
dial$nopulse <T> ; /60/
dial$blind <^A> ; /60/
mod$comment <DEC Standalone DF224>
mod$res <Attached> ,CONNECT
mod$res <Busy> ,FAILED
mod$res <Disconnected> ,FAILED
mod$res <Error> ,FAILED
mod$res <No answer> ,FAILED
mod$res <No dial tone> ,FAILED
mod$res <Speed:> ,FAILED
define hayes ,<HAYES> ; actually, its a VOLKSMODEM 12
dial$time 35. ; that we are testing with. It's
wake$string <ATZ V1^M> ; supposed to be compatible.
wake$rate 0
wake$ack <OK>
wake$prompt <OK>
dmod$string <>
dmod$prompt <>
dial$string <AT D %s^M>
dial$rate 0
dial$echo 1
define microcom,<MICROCOM> ;
dial$time 35.
wake$string <4445^MSE2^MS1C0^MSCE ON^M>
wake$rate 10
wake$ack <!>
wake$prompt <!>
dial$string <D%s^M>
dial$rate 10
dial$echo 1
mod$res <CONNECT> ,CONNECT
mod$res <NO CONNECT> ,FAILED
mod$res <!> ,FAILED
mod$comment <MicroCom SX1200>
; The following entry was added by edit (RTM01).
define r212a ,<R212A> ; RIXON R212A Intelligent modem.
dial$time 60. ; Long timeout for overseas.
wake$string <^M^M>
wake$rate 10 ; wait 8 ticks (8/60 second)
wake$ack <RIXON R212A INTELLIGENT MODEM>
wake$prompt <$>
dmod$string <K>
dmod$prompt <NUMBER:>
dial$string <%s^M>
dial$rate 10
; dial$ack <^M>
; dial$confirm <^M>
dial$go <DIALING:>
dial$echo 1
mod$comment <RIXON R212A Intelligent Modem>
mod$res <ON LINE> ,CONNECT
mod$res <ON-LINE> ,CONNECT
mod$res <NO ANSWER> ,FAILED
mod$res <DEAD LINE> ,FAILED
mod$res <BUSY> ,FAILED
mod$res <END D> ,INFO
mod$res <RINGING> ,INFO
define protms ,<PROTMS> ; this one has to use QIOS for dial
ext$dial tmsdial ; we will have to catch this one in
; a not so clean manner. Waiting for
; Steve Kovey's code for support.
.sbttl define user defined modem structure
; This one <USER_DEFINED> MUST be the last one in the list. The link
; must be inserted at run time via a call to FINDMODEM with a known
; type, like CALLS FINDMO,<#vadid>.
; NONE of the field macros used above will work for this since the
; psect it's in is global.
; Setting up the fields is fairly simple, for example, setting the
; wakeup string would be:
;
; mov #usermd ,r4
; strcpy #udiawake,argbuf
; mov #udiawake,wake.string(r4) ; stuff wakeup string addr
;
; And setting a reponse string, assuming CONNECT is success
;
; mov #usermd ,r4 ; address of data structure
; mov #contxt ,res.header(r4) ; and stuff the list in
;
; contxt: .word faitxt ; link to next
; .word 1 ; > 0 for indicating connect
; .asciz /CONNECT/ ; the string itself
; .even ; please
; faitxt: .word 0 ; no link to next
; .word -1 ; flag call failed
; .asciz /NOCONNECT/ ; the text if it fails
; .even ; please
;
; Where udiawake was a area in the root, defined in K11DAT.MAC
; Keep in mind that the code which looks for a response will NOT
; exit until (1) nothing happens for 30 seconds or (2) it finds
; a match in the list with a non-zero status.
define usermd ,<USER_DEFINED>,GLOBAL ; This MUST be the last one
; No more definitions allowed past here
.sbttl local macros to make life simpler
.macro lowcase s
mov s ,r0
call lowcas
.endm lowcase
.macro sleep time
calls suspend ,<time,#0>
.endm sleep
.macro tsleep ticks
calls suspend ,<#0,ticks>
.endm tsleep
.macro ttputstr s
mov r1 ,-(sp)
mov s ,r1
call doput
mov (sp)+ ,r1
.endm ttputstr
.macro ttputc c
clr -(sp)
bisb c ,(sp)
mov sp ,r0
calls binwri ,<r0,#1,#lun.ti>
tst (sp)+
.endm ttputc
.macro ttgetc wait
; lun.ti is the remote lun
.if b ,wait
.ift
calls xbinread,<#lun.ti,#0>
.iff
calls xbinread,<#lun.ti,wait>
.endc
.endm ttgetc
.macro waitfor s ,time,fail
.if b ,time
.ift
clr -(sp)
.iff
mov time ,-(sp)
.endc
mov s ,-(sp)
call waitfor
.if nb, fail
tst r0
beq fail
.endc
.endm waitfor
.macro waitc c ,time
clr -(sp)
mov sp ,r0
movb c ,(r0)
.if b ,time
.ift
clr -(sp)
.iff
mov time ,-(sp)
.endc
mov r0 ,-(sp)
call waitfor
tst (sp)+
.endm waitc
.macro didweget s,pat,status,ret,?b
.save
.psect string
$$ = .
.asciz /pat/
.restore
mov #$$ ,-(sp)
mov s ,-(sp)
call didweget
tst r0
beq b
mov status ,ret
b:
.endm didweget
remmod = ter$cc
.sbttl REDIAL command
.psect $code
.enabl lsb
c$redi::mov argbuf ,r3 ; /40/ argbuf address
mov phnum ,r2 ; /40/ address of phone number
mov #1 ,r4 ; /40/ default repeat count
tstb @r3 ; /40/ Any repeat count passed ?
beq 5$ ; /40/ No
calls l$val ,<r3> ; /40/ retry count
mov r1 ,r4 ; /40/ save repeat count
tst r0 ; /40/ success ?
beq 5$ ; /40/ yes
message <Invalid number!>,cr
br 90$ ; /40/ exit
5$: tstb @r2 ; /40/ Any real phone number today?
bne 10$ ; /40/ yes
message <No previous number!>,cr
br 90$ ; /40/ exit if no DIAL command
10$: message <Using: > ; /40/ echo the number we will use
print r2 ; /40/
message ; /40/ crlf
strcpy r3 ,r2 ; /40/ copy old phone num to 'argbuf'
20$: tst cccnt ; /40/ control C abort ?
bne 90$ ; /40/ Yes, exit this loop NOW
mov r4 ,-(sp) ; /40/ save looping counter
call c$dial ; /40/ no, try dialing
mov (sp)+ ,r4 ; /40/ restore looping counter
tst r0 ; /40/ success ?
beq 100$ ; /40/ yes
sob r4 ,20$ ; /40/ No, try again please
90$: mov #-1 ,r0 ; /40/ failure
inc status ; /45/ Set global flag also
100$: return
.dsabl lsb
set$mo::strcpy #modem ,argbuf
call findmodem
tst r0
bne 100$
mov #-1 ,r0
inc status ; /45/ Global flag also
return
100$: clr r0
return
.sbttl the DIAL command
.psect $code
.enabl lsb
c$dial::strcpy phnum ,argbuf ; /40/ save the phone number
tstb ttdial ; check for a real terminal name
bne 10$ ; ok
message <Please use the SET LINE command first>,cr
br 90$ ; exit
10$: tstb modem ; check for a SET MODEM command
bne 20$ ; ok
tst proflg ; /39/ is this a pro/350 ?
beq 15$ ; /39/ no, fatal error
cmpb ttdial ,#'X&137 ; /39/ check for XTn:
bne 15$ ; /39/ no
cmpb ttdial+1,#'T&137 ; /39/ if so, must be TMS on P/OS
bne 15$ ; /39/ no, so no modem type fatal
strcpy #modem ,protms+mod.str ; /39/ stuff 'PROTMS' in please
br 20$ ; /39/ lookup the modem now
15$: message <Please use the SET MODEM command first>,cr
br 90$
20$: call findnumber ; /45/ Perhaps a SET PHO NUM ?
bcs 90$ ; /51/
call findmodem ; do we know about this modem ?
mov r0 ,modtype ; save the address of descriptor
beq 90$ ; no luck, exit with failure
mov ext.dial(r0),r1 ; /39/ need external routine to dial?
beq 30$ ; /39/ no
jsr pc ,@r1 ; /39/ yes, call it then
br 120$ ; /39/ and exit
30$: mov dial.string(r0),r0 ; /39/ get dial formatting string addr
tstb @r0 ; /39/ anything there ?
bne 40$ ; /39/ yes
message <A dial formatting string has not been defined>,cr
br 90$ ; /39/ exit
40$: calls ttyini ,<#ttname,#lun.ti,#remmod>
tst r0 ; did we get a successful open on line?
bne 80$ ; no, emit some sort of error message
call tidias ; /45/ Set characteristics (TC.DLU)
call getatn ; try to get modems attention
tst r0 ; did getting modems attn succeed?
beq 90$ ; no
call dodial ; actually try to dial the number now
mov r0 ,-(sp) ; /45/ Save status return
call tidiar ; /45/ Reset characteristics
mov (sp)+ ,r0 ; /45/ Restore status return
tst r0 ; returns 1 for success, zero else
beq 90$ ; failure
br 100$ ; success, return(0) re normal k11
80$: direrr r0 ; emit an error message and exit
90$: mov #-1 ,r0
br 110$
100$: clr r0
110$: call 200$
120$: tst r0 ; /45/ Errors ?
beq 130$ ; /45/ No
inc status ; /45/ Yes, set into global flag
130$: return
200$: mov r0 ,-(sp)
calls ttyfin ,<#ttname,#lun.ti> ; close the terminal up now
mov (sp)+ ,r0
return
.dsabl lsb
.sbttl match type of modem
.enabl lsb
; FINDMODEM
;
; Passed: nothing, assumes MODEM name is in global modem::
;
; Return: r0 address of structure for the modem
; r0 = 0 if the modem type could not be found
;
; Remark: It might be better to call PRINTM to display messages
; to better control the case if we got spawned under RSX
; or RSTS so we could avoid I/O and instead return some
; status info.
findmo::tst $modtail ; /39/ Is the usre mode defined?
bne 5$ ; /39/ Yes
mov #usermd ,$modtail ; /39/ no, insert it please
5$: mov #modinf ,r3 ; get address of head of list
10$: strcmp #modem ,mod.str(r3) ; check for a match please
tst r0 ; a match
beq 80$ ; yes
mov mod.next(r3),r3 ; no, try the next one please
bne 10$ ; keep going
message <This modem type is unknown. The known modem types>,cr
message <are:>,cr
message
mov #modinf ,r3 ; now print the list of modems
20$: print mod.str(r3) ; first one
strlen mod.str(r3) ; /39/ length of modem type
sub #40 ,r0 ; /39/ tab over please
neg r0 ; /39/ make it > 0
30$: print #200$ ; /39/ a space
sob r0 ,30$ ; /39/ next please
print mod.com(r3) ; /39/ dump comment string
message ; cr/lf
mov mod.next(r3),r3 ; next one in list
bne 20$ ; ok
br 90$ ; exit with failure
80$: mov r3 ,r0 ; return address of structure
br 100$ ; bye
90$: clr r0 ; failure
100$: return ; bye
.save
.psect $Pdata ,d
200$: .byte 40,0
.restore
global <modem>
.dsabl lsb
.sbttl Look for defined phone numbers
.enabl lsb
; Added /45/ 20-Feb-86 13:00:50 BDN
;
; Check through linked list for phone number definitions
findnu: mov r3 ,-(sp) ; Save this
mov r2 ,-(sp) ; Save this one also
cmpb @argbuf ,#'0 ; Only if not number in first pos
blo 5$ ; Ok
cmpb @argbuf ,#'9 ; Well ?
bhi 5$ ; No
clc ; Success, exit
jmp 100$ ; A number, exit please
5$: mov #pnhead ,r2 ; Get listhead
;- calls tlog ,<argbuf> ; /47/ Check for logical names
; Loop a little
10$: mov (r2) ,r2 ; Get next entry
beq 90$ ; Nothing there
mov r2 ,r3 ; Get address of text
add #2 ,r3 ; +2 for data
mov #ntemp ,r0 ; Store temp here
20$: cmpb (r3) ,#40 ; All done looking ?
beq 30$ ; Yes
movb (r3)+ ,(r0)+ ; No, copy more of the NAME
bne 20$ ; All done
30$: clrb (r0) ; Insure .asciz please
strcmp #ntemp ,argbuf ; Check for a match please
tst r0 ; Find a match ?
bne 10$ ; No, check the next one
;
40$: inc r3 ; Point to number field
tstb (r3) ; Anything really there?
beq 100$ ; No, exit please
message <Using: > ; Print the translation out
strcpy argbuf ,r3 ; Copy it over
print argbuf ; ...
message ; ....
clc ; Success
br 100$ ; Exit
90$: print #npr ; /51/ Dump a prompt
mov #ttbuff ,r2 ; /51/ Set address up
calls kbread ,<r2> ; /51/ Read the response
bicb #40 ,r2 ; /51/ Cvt to lower case
cmpb @r2 ,#15 ; /51/ A CR
beq 95$ ; /51/ Ok
tstb @r2 ; /51/ Null ?
beq 95$ ; /51/ Yes, success
cmpb @r2 ,#'Y&137 ; /51/ A 'YES'
beq 95$ ; /51/ Y, success
sec ; /51/ No, failure
br 100$ ; /51/ Exit
95$: clc ; /51/ Success
100$: mov (sp)+ ,r2 ; Pop and
mov (sp)+ ,r3 ; pop again, then...
return ; Exit
.dsabl lsb
.save
.psect string
.even
ntemp: .blkb 200
npr: .asciz /No translation found for number. Continue <Yes> ? /
.even
.restore
global <pnhead>
.sbttl GETATN wake the modem up
.enabl lsb
; Input: MODTYPE address of modem descriptor
; Return: R0 zero on failure, else success
;
; In case the modem is already awake (at command prompt mode)
; we will dump the string, wait for the ackknowledgment and
; then loop until we are sure there is no more data. For ex-
; ample, the VA212 will send back a INVALID COMMAND\n* string
; for the ^E and one also for the <CR>. We could, of course,
; first send the modem it's IDLE command, but there are times
; when that may be undesirable, like when the modem is being
; accessed via some sort of LAN or PABX.
getatn::save <r1,r2,r3,r4> ; perhaps save something
mov modtype ,r4 ; get address of structure
call eatjunk ; trash stuff that may be waiting
mov #3 ,r3 ; loop a little to get modem going
mov wake.string(r4),r2 ; Get address of wakeup string
10$: ttputc (r2)+ ; We may need to insert delays
tstb @r2 ; for the faster modems.
beq 15$ ; All done?
tsleep wake.rate(r4) ; Not done, pause if need be
br 10$ ; And do some more
15$: waitfor wake.prompt(r4),#3,20$ ; now wait for an ack
br 25$ ; success
20$: call eatjunk ; trash stuff that may be waiting
mov wake.string(r4),r2 ; reset wakeup string
sob r3 ,10$ ; next please
br 90$ ; a complete failure, exit
25$: message <Modem in command mode>,cr
30$: call eatjunk
mov #1 ,r0 ; return(success)
br 100$ ; and exit
90$: message <Failed to get modems attention>,cr
clr r0
100$: unsave <r4,r3,r2,r1>
return
.dsabl lsb
.sbttl actually dial the number
.enabl lsb
; Note that the waitfor routine, called by macro of same name will
; exit immediatly if the string to compare against is NULL, thus it
; won't hurt anything to call it for modems that may not respond.
; One other problem is in inserting delays into dumping strings to
; the modem in that the smallest interval RSTS/E can delay is one
; second. As always in Kermit-11, we must try to allow for code to
; function under all execs, not just RT or just RSTS or .....
dodial: save <r2,r3,r4,r5> ; save registers that we might zap
mov #buffer ,r3 ; and a pointer to it also
mov modtype ,r4 ; get address of modem descriptor
mov #1 ,r2 ; since RSTSE can't sleep < 1 second
mov #cccnt ,r5 ; control C int flag
call fmtstr ; format the dialing string
tst dialmode ; /45/ Should we force PULSE or TONE?
beq 5$ ; /45/ Nothing
bmi 4$ ; /45/ Tone
ttputs dial.pulse(r4) ; /45/ See if user selected PULSE
br 5$ ; /45/ Now get the thing to dial
4$: ttputs dial.nopulse(r4) ; /45/ Force TONE dialing
5$: ttputs dmod.string(r4) ; dump the prompt for dialing out
waitfor dmod.prompt(r4),#4,80$ ; wait for a response
call eatjunk ; let things settle a bit
10$: tstb (r3) ; end of it all ?
beq 40$ ; yes
tst @r5 ; user interupt happen ?
bne 90$ ; yes, exit now
ttputc (r3)+ ; no, dump one character out
tst dial.echo(r4) ; does it echo characters after each
beq 20$ ; character ?
ttgetc #1 ; yes, just wait a second for the echo
20$: dec r2 ; time to take a short nap ?
bne 10$ ; no
tst dial.rate(r4) ; do we REALLY need to suspend ?
beq 30$ ; no
tsleep dial.rate(r4) ; yes, do it (RSTS of course, can't
30$: mov #1 ,r2 ; sleep < 1 but RSX & RT can).
br 10$ ; may want to insert delays here
40$: mov #buffer ,r3 ; restore buffer pointer
waitfor dial.ack(r4),#4 ; wait for number being echoed perhaps
sleep #1 ; another kludge (mostly RSTS again)
tst @r5 ; control C or other abort?
bne 90$ ; yes
ttputs dial.conf(r4) ; stuff a confirm (ok if null)
waitfor dial.go(r4),#5,100$ ; maybe wait for any confirm that its
message <Modem dialing>,cr ; dialing the number?
call getsts ; get final result of the call please
tst r0 ; success ?
bne 110$ ; yes
br 100$ ; no, dump failure message
80$: strcpy #buffer,#nodprompt ; copy message for no dial prompt
br 100$ ; and dump message
90$: strcpy #buffer,#abort ; user interupt message
100$: tst cccnt ; /45/ Did this die from a control C
beq 105$ ; /45/ No
ttputs dial.xabort(r4) ; /45/ Yes, get the modem to STOP
105$: ttputs dial.idle(r4) ; /45/ Reset into IDLE state
message <Call failed > ; oops
print #buffer ; why it did
message ; <CR><LF>
clr r0 ; failure
br 120$ ; exit
110$: message <Connection made, use the CONNECT command to access remote>
print #bell ; /50/ Beep
call getsys ; /48/ Don't wait unless rsx flavor
cmpb r0 ,#SY$MPL ; /48/ M+ ?
beq 115$ ; /48/ Yes, wait a moment
cmpb r0 ,#SY$11M ; /48/ RSX11M 4.x ?
bne 116$ ; /48/ No, don't suspend
115$: sleep #2 ; /45/ Wait a moment
116$: message ; successful call
mov #1 ,r0 ; exit
120$: unsave <r5,r4,r3,r2> ; and registers
return ; and exit
.dsabl lsb
.sbttl GETSTS Get final result of dial
; Passed: R4 --> structure describing modem
;
; Return: R0 1 for success, else zero
;
; This is the messy part as we have to anticipate response from
; whatever modem type we are trying to use.
; Much of the attempts to do timeouts is made very difficult by
; the fact that out of P/OS, RT11, RSX11M/m+ and RSTS/E, !ONLY!
; RSTS is unable to schedule time based AST's (mrkt$s and so on)
; Timer AST's would greatly help out here.
;
; Define dispatch table to take special actions for each modem type
dispatch basedsp=moddsp,baseval=modlst,default=.default
;- /39/ dispatch $V2PA ,.v2pa ; standalone VA212PA
;- /39/ dispatch $V2PAR ,.v2par ; rack mount VA212PAR
;- /39/ dispatch $VADIC ,.vadic ; most vadics (same as 212PA)
dispatch $HAYES ,.hayes ; HAYES (really volksmodem12)
;- /45/ dispatch $DF100 ,.df100 ; DEC DF112
;- /45/ dispatch $DF200 ,.df200 ; DEC DF2xx series
dispatch $DF03 ,.df03 ; DEC DF03
dispatch
.save
.psect
.psect string
defmsg: .asciz / No connection/
exring: .asciz / Excessive RINGING... messages returned/
abort: .asciz / Operation aborted under user interupt/
nodpro: .asciz / No response or invalid response to dial command/
.restore
CONNECT = 1
FAILED = -1
status = 0
nrings = 2
temp = 4
locsiz = 10
getsts::tst diatmo ; /46/ Timeout set?
bne 5$ ; /46/ Yes
..diat == . + 2 ; /46/ Patchable
mov #30. ,diatmo ; /46/ No, set it up
5$: sub #locsiz ,sp ; allocate local r/w data
mov sp ,r5 ; and a pointer
mov #10 ,nrings(r5) ; for VA212 PA, excessive ringing
clr temp(r5) ; temp
clr (r5) ; status = 0
.assume status eq 0 ; assertion
mov #buffer ,r3 ; a buffer pointer
strcpy r3 ,#defmsg ; copy a message over
10$: tst (r5) ; while ( status == 0 )
bne 90$ ; exit with result
mov #buffer ,r3 ; a buffer pointer
20$: ttgetc diatmo ; wait for a status return
tst r0 ; successful ?
beq 30$ ; yes
mov #FAILED ,(r5) ; no
br 70$ ; exit loop
30$: tstb r1 ; /51/ Never suffer imbedded NULLS
beq 20$ ; /51/ Ignore if such
bicb #^C177 ,r1 ; insure a real seven bit character
movb r1 ,(r3)+ ; copy the byte over
clrb (r3) ; insure we stay .asciz
tst res.bin(r4) ; exit loop on single character I/O?
bne 40$ ; yes
cmpb r1 ,#CR ; carriage return finally found ?
beq 40$ ; yes
cmpb r1 ,#LF ; no, but a line feed will do nicely
bne 20$ ; not a <LF>, try some more input then
40$: scan mod.val(r4),#modlst ; do a crude case statement
asl r0 ; word indexing
jsr pc ,@moddsp(r0) ; simple
70$: br 10$ ; next please
90$: mov #1 ,r0 ; assume success
tst (r5) ; failure ?
bpl 100$ ; no
clr r0 ; return(0) for failure
100$: add #locsiz ,sp ; pop temps and exit
return ; exit
global <diatmo> ; /46/
.sbttl dispatch routines for specific modem (vadic, hayes)
.enabl lsb
; The DEFAULT entry will read possible responses, and their
; message classes, from a linked list whose first address is
; in RES.HEADER(modem_address). Each list entry has a link to
; the next one (or a zero), a message class (lt zero if fail,
; == zero for ringing message, and gt zero for SUCCESS ). If
; a modem has no entries at all, the routine will return a
; failed call. While this method can tend to add size to this
; module as similiar modems must have separate list, it is a
; bit more general, while allowing us at some future time to
; provide a SET DIAL command to dynamically create the modem
; data structure for a previously undefined modem type. Added
; edit 2.39, 04-DEC-1985 10:17, Brian Nelson.
;
; We do not need a real definition for modem type DEFAULT as
; it is not possible to ever get this far if the type is un-
; defined.
;
; Default:
.default:
save <r3> ; /39/ save temp register
mov res.head(r4),r3 ; /39/ get listhead of responses
beq 90$ ; /39/ No responses defined ?
10$: mov r3 ,-(sp) ; /39/ get address of ascii text
add #4 ,(sp) ; /39/ 4 byte offset for text
mov #buffer ,-(sp) ; /39/ Stuff address of response
call didweget ; /39/ check for the response
tst r0 ; /39/ find the text in the list?
bne 20$ ; /39/ yes, get the response class
mov (r3) ,r3 ; /39/ no, get the next in the list
bne 10$ ; /39/ something is left
br 100$ ; /39/ nothing is left, continue...
20$: mov 2(r3) ,(r5) ; /39/ response class
bne 100$ ; /39/ either success or failure
PRINT #buffer ; /54/
MESSAGE ; /54/
dec nrings(r5) ; /39/ Choose a point to cut it off
bne 100$ ; /39/ after a lot of ringing messages.
strcpy #buffer,#exrings ; /39/ copy an informative message. Stop
ttputs wake.string(r4) ; /39/ the modem from trying too hard
waitfor wake.prompt(r4),#2 ; /39/ eat any possible response please
90$: mov #FAILED ,(r5) ; /39/ exit
100$: unsave <r3> ; /39/ pop r3 and exit
return ; /39/ bye
.dsabl lsb
.sbttl Special cases
.enabl lsb
; Case HAYES:
.hayes: didweget #buffer,<CONNECT>,#CONNECTED,(r5)
didweget #buffer,<NO CARRIER>,#FAILED,(r5)
didweget #buffer,<BUSY>,#FAILED,(r5)
didweget #buffer,<ERROR>,#FAILED,(r5)
didweget #buffer,<RING>,#1,r0 ; macro clears r0 if string not found
tst r0 ;
beq 10$ ; and ring and ring and ring forever it
message <Remote phone is ringing>,cr
dec nrings(r5) ; would seem. so chose a point to cut
bne 10$ ; it off at some point
strcpy #buffer,#exrings ; copy an informative message and stop
ttputs wake.string(r4) ; the modem from trying too hard
waitfor wake.prompt(r4),#2 ; eat the OK please
mov #FAILED ,(r5) ; exit
10$: return
.dsabl lsb
; Case DF03:
.df03: didweget #buffer,<A>,#CONNECTED,(r5)
didweget #buffer,<B>,#FAILED,(r5)
return
.sbttl format dial string (sprintf works a lot better)
; Passed: R3 address of buffer to place result
; ARGBUF the number to insert
fmtstr: mov r3 ,-(sp)
mov dial.string(r4),r2 ; point to the dial formatting string
10$: tstb (r2) ; done ?
beq 50$ ; yes
cmpb (r2) ,#'% ; look for a format effector
bne 30$ ; no
mov argbuf ,r0 ; Assume phone number insertion
cmpb 1(r2) ,#'s!40 ; %s formatting ?
beq 20$ ; no
cmpb 1(r2) ,#'s&137 ; %S formatting ?
beq 20$ ; Yes
mov dial.wait(r4),r0 ; No, assume pause string formatting
cmpb 1(r2) ,#'p!40 ; %P for pause string?
beq 20$ ; Yes
cmpb 1(r2) ,#'p&137 ; check both cases
beq 20$ ; No
;
cmpb 1(r2) ,#'M&137 ; /54/ Mode (ie PULSE, TONE)
beq 15$ ; /54/ Found it
cmpb 1(r2) ,#'m!40 ; /54/ ...
bne 16$ ; /54/ Nope
15$: mov dial.pulse(r4),r0 ; /54/ Assume PULSE dialing
tst pulse ; /54/ Ever SET PHONE PULSE/TONE?
beq 25$ ; /54/ No, ignore string
bmi 20$ ; /54/ SET PHONE PULSE
mov dial.nopulse(r4),r0 ; /54/ SET PHONE TONE
br 20$ ;
16$: cmpb 1(r2) ,#'B&137 ; /54/ SET PHONE BLIND?
beq 17$ ; /54/ Is this the formatting char?
cmpb 1(r2) ,#'b!40 ; /54/ No, perhaps lower case?
bne 30$ ; /54/ No, copy data then
17$: tst blind ; /54/ Ever do the SET PHONE BLIND?
beq 25$ ; /54/ No, ignore string
mov dial.blind(r4),r0 ; /54/ Yes, insert the data then.
;
20$: movb (r0)+ ,(r3)+ ; copy a byte please
bne 20$ ; not a null, next please
dec r3 ; fix current pointer up
25$: inc r2 ; skip over the '%' please
br 40$ ; next please
30$: movb (r2) ,(r3)+ ; not formatting, copy character
40$: inc r2 ; skip over current character now
br 10$ ; next
50$: clrb (r3) ; insure dial string is .asciz
mov (sp)+ ,r3 ; restore pointer and exit
return
.sbttl misc util routines
.enabl lsb
; WAITFOR(s,timeout)
;
; Wait for the character string in S
;
; Passed: 2(sp) string
; 4(sp) timeout
; Return: 1 success
; 0 timeout
waitfor:save <r2,r3,r4>
mov 2+6(sp) ,r4 ; string we are looking to get
mov 2+10(sp),r3 ; timeout in seconds
10$: movb (r4)+ ,r2 ; next character to await
beq 30$ ; success, we can leave now
20$: ttgetc r3 ; wait at most r3 seconds please
tst r0 ; success ?
bne 90$ ; no (i/o routines use r0 for err code)
bicb #^C177 ,r1 ; remove parity always
tstb r1 ; /51/ Ignore imbedded NULLS
beq 20$ ; /51/ ....
cmpb r1 ,r2 ; did we get the correct character?
bne 20$ ; no, keep waiting then
br 10$ ; found it, check for next character
30$: mov #1 ,r0 ; success
br 100$ ; exit
90$: clr r0 ; failure, return(0)
100$: unsave <r4,r3,r2>
mov (sp) ,4(sp) ; move return address up and exit
cmp (sp)+ ,(sp)+ ; fix stack
return ; exit
.dsabl lsb
didwege:save <r1,r2,r3>
mov 2+10(sp),r3 ; string to look for
mov 2+6(sp) ,r2 ; string to find it in
lowcase r3 ; /45/ Lowercase it in buffer
strlen r3 ; string length of pattern
mov r0 ,r1 ; save it
lowcase r2 ; /45/ Lowercase it in buffer
strlen r2 ; length of source string
calls instr ,<r2,r0,r3,r1> ; simple (use funct we already have)
unsave <r3,r2,r1> ; pop temps and exit
mov (sp) ,4(sp) ; move return address up and exit
cmp (sp)+ ,(sp)+ ; fix stack
return ; exit
eatjunk:save <r0,r1>
10$: ttgetc #1
tst r0
beq 10$
unsave <r1,r0>
return
; Added /45/
lowcas: mov r0 ,-(sp) ; Save starting address
10$: tstb (r0) ; End of the line yet?
beq 100$ ; Yes, exit then
cmpb (r0) ,#'A&137 ; A big letter?
blo 20$ ; No
cmpb (r0) ,#'Z&137 ; A big letter?
bhi 20$ ; No
bisb #40 ,(r0) ; Yes, make it lower
20$: inc r0 ; Next please
br 10$ ; and check it
100$: mov (sp)+ ,r0 ; Return starting address
return ; Exit
doput: strlen r1
tst r0
beq 10$
calls binwri ,<r1,r0,#lun.ti>
10$: return
.sbttl Show Modem/Dial
.enabl lsb
shomod::
shodia::call findmodem ; Do we know about this modem ?
mov r0 ,r4 ; Save the address of descriptor
bne 5$ ; No luck, exit with failure
MESSAGE <No modem type has been SET>,CR
return ;
5$: mov #slist ,r3 ; Info list start
tst ext.dial(r4) ; Is this a built-in, like PRO/TMS?
beq 10$ ; No
MESSAGE <This is an internal modem>,CR
jmp 100$ ; Exit
;
10$: movb (r3)+ ,r1 ; Type of data (1=String,0=Number)
movb (r3)+ ,r2 ; Offset, zero implies end.
beq 60$ ; All done
add r4 ,r2 ; Move to the correct offset
PRINT r3 ; Dump the header
20$: tstb (r3)+ ; Now look for the end of it
bne 20$ ; Not yet
tstb r1 ; Data type, zero is numeric
bne 30$ ; Ascii
DECOUT (r2) ; Dump the data
br 50$ ; Next please
30$: mov (r2) ,r0 ; Get the string data address
beq 40$ ; Nothing there
tstb @r0 ; Again
beq 40$ ; Nothing has been set
call unfmts ; Convert and print it
PRINT r0 ; Do it
br 50$ ; Next
40$: MESSAGE <The option has not been SET>
50$: MESSAGE ;
br 10$ ; Next
;
60$: mov res.head(r4),r3 ; Response header
beq 100$ ; Nothing present
MESSAGE ;
MESSAGE <Modem message Message Class>,CR
MESSAGE ;
65$: mov r3 ,r2 ; Get the response address
beq 100$ ; All done
add #4 ,r2 ; Offset is four
STRCPY #buffer ,r2 ; Copy it
STRLEN #buffer ; Length
sub #24. ,r0 ; Amount to stuff in
neg r0 ; Make it positive
mov r0 ,r5 ; Save it in a safe place
ble 75$ ; Avoid this please
70$: STRCAT #buffer ,#200$ ; Do it
sob r5 ,70$ ; A few times
75$: PRINT #buffer ; Dump the text
tst 2(r3) ; What is the message class?
bmi 85$ ; If < 0, failure to connect
beq 80$ ; If == 0 just informative
MESSAGE <Successfull connect>,CR;
br 90$ ; Next please
80$: MESSAGE <Informative message>,CR;
br 90$ ; Next please
85$: MESSAGE <Failure to connect>,CR;
90$: mov (r3) ,r3 ; Pick up link to next
br 65$ ; Next please
;
100$: return
.Save
.psect $Pdata,d
200$: .asciz / /
.macro DES Type,Offset,Title
.if B, Type
.byte 0,0
.iff
.byte Type,Offset
.asciz @Title@
.endc
.endm DES
slist: DES 1,mod.comment,<Modem type: >
DES 1,wake.string,<Wakeup string: >
DES 1,wake.ack ,<Response to wakeup: >
DES 1,dial.string,<Format for dialing: >
DES 0,dial.rate, <Delay for dialing: >
DES
.Even
.Restore
.end