title   'Overlay for the Morrow Multi I/O Board and/or 8250 ACE'
;
; MXO-MM10.ASM -- MEX Overlay file for the Morrow Multi I/O Board.  05/28/84
;
REV     EQU     10      ;V 1.0
;
; This overlay adapts the MEX modem program to the Morrow Multi I/O board
; which uses the 8250 ACE.  It also can be used with an 8250 ACE alone by
; setting MORMIO to FALSE.
;
; This overlay is capable of setting baud rate and setting port number
; (via the SET command), setting baud rate from the phone library, dis-
; connecting the  modem, and sending a break.
;
; *NOTE* This overlay contains two conditionals and uses DTR to disconnect
; the modem.  SET THE DISC EQU TO FALSE in MXO-SMxx.ASM if using that overlay.
; DISC is handled here with DTR.
;
NO      EQU     0
YES     EQU     NOT NO
FALSE   EQU     NO
TRUE    EQU     YES
;
; Set the following two equates as needed:
;
MORMIO  EQU     TRUE    ;true if using Morrow Multi I/O card, false for
;                        stand alone 8250 ACE.
SMDM    EQU     TRUE    ;True if using Smartmodem 1200, false and/or change
;                        code for other modems with Morrow Multi I/O
;
; Also, be sure to set your port address and desired baud rates below
;
; NOTE:  I have tested this overlay to the extent possible with MORMIO, SMDM,
; or both FALSE.  However, I could not conduct a full operational test since
; I do not have a properly configured machine.  Please report any bugs,
; suggestions to: Phil Cary, Mesilla Valley RCP/M, (505) 524-6920.
;
; Calling conventions for the various overlay entry points are detailed more
; fully in the PMMI overlay (MXO-PMxx.ASM, where xx=revision number)
;
; History as a MEX overlay
;
; 05/28/84 - 1st version      - Phil Cary, Mesilla Valley RCP/M
;
; Derived from: MXO-PM10.ASM, Ron Fowler
;               MXO-SM11.ASM, Ron Fowler
;               MXO-GB10.ASM, Ron Fowler
;               SMDMM.ASM, Phil Cary (overlay for MDMxxx)
;
; MEX service processor stuff
;
MEX     EQU     0D00H           ;address of the service processor
INMDM   EQU     255             ;get char from port to A, CY=no more in 100 ms
TIMER   EQU     254             ;delay 100ms * reg B
TMDINP  EQU     253             ;B=# secs to wait for char, cy=no char
CHEKCC  EQU     252             ;check for ^C from KBD, Z=present
SNDRDY  EQU     251             ;test for modem-send ready
RCVRDY  EQU     250             ;test for modem-receive ready
SNDCHR  EQU     249             ;send a character to the modem (after sndrdy)
RCVCHR  EQU     248             ;recv a char from modem (after rcvrdy)
LOOKUP  EQU     247             ;table search: see CMDTBL comments for info
PARSFN  EQU     246             ;parse filename from input stream
BDPARS  EQU     245             ;parse baud-rate from input stream
SBLANK  EQU     244             ;scan input stream to next non-blank
EVALA   EQU     243             ;evaluate numeric from input stream
LKAHED  EQU     242             ;get nxt char w/o removing from input
GNC     EQU     241             ;get char from input, cy=1 if none
ILP     EQU     240             ;inline print
DECOUT  EQU     239             ;decimal output
PRBAUD  EQU     238             ;print baud rate
;
PRINT   EQU     9               ;BDOS/MEX print-string function call
;
BELL    EQU     7               ;bell
TAB     EQU     9
CR      EQU     13              ;carriage return
LF      EQU     10              ;linefeed
ESC     EQU     1BH             ;escape
;
;
       IF MORMIO
;
;These are the equates for the Morrow Multi I/O base port and group selection.
;Change as needed to match your configuration.
;
; Morrow Multi I/O port equates
;
BPORT   EQU     0F8H            ;base port for Morrow Multi I/O
GPORT   EQU     BPORT+7         ;group select port
MPORT   EQU     2               ;default group in use for modem
;                                (2nd serial port)
       ENDIF
;
;
       IF NOT MORMIO
;
; 8250 port equates
;
BPORT   EQU     00H     ;If using stand alone 8250, put base port address here.
;
       ENDIF
;
MODDAT: EQU     BPORT           ;data port(dlab=0)
MODIER: EQU     BPORT+1         ;interrupt enable register(dlab=0)
MODLCR: EQU     BPORT+3         ;line control register
MODMCR: EQU     BPORT+4         ;modem control register
MODLSR: EQU     BPORT+5         ;line status register
LBAUDP: EQU     BPORT           ;LSB baud rate divisor latch(dlab=1)
MBAUDP: EQU     BPORT+1         ;MSB baud rate divisor latch(dlab=1)
;
;These are equates for the 8250 register masks or control words.
;
;line control register
;
wls0    equ     00000001b       ;for eight bit word
wls1    equ     00000010b       ;for eight bit word
sbrk    equ     01000000b       ;set break
dlab    equ     10000000b       ;baud rate divisor latch active
;
;modem control register
;
dtr     equ     00000001b       ;DTR on
;
;line status register
;
dr      equ     00000001b       ;data ready
thre    equ     00100000b       ;transmitter holding register empty
;
;
; Baud rate parameters - change EQU to 0000h if you do not wish to support
; a particular baud rate.
;
BD110:  EQU     0417H   ;110 baud
BD300:  EQU     0180H   ;300 baud
BD450:  EQU     0120H   ;450 baud
BD600:  EQU     00C0H   ;600 baud
BD710:  EQU     0000H   ;710 baud (not supported)
BD1200: EQU     0060H   ;1200 baud
BD2400: EQU     0030H   ;2400 baud
BD4800: EQU     0018H   ;4800 baud
BD9600: EQU     000CH   ;9600 baud
BD19200 EQU     0006H   ;19200 baud
;
       ORG     100H
;
; Change the clock speed to suit your system
;
       DS      3               ;(for  "JMP   START" instruction)

       DB      NO              ;yes=PMMI S-100 Modem                   103H
       DB      YES             ;yes=HAYES Smartmodem, no=non-PMMI      104H
       DB      'T'             ;T=touch, P=pulse (Smartmodem-only)     105H
CLOCK:  DB      40              ;clock speed in MHz x10, 25.5 MHz max.  106H
                               ;20=2 MHh, 37=3.68 MHz, 40=4 MHz, etc.
MSPEED: DB      5               ;0=110 1=300 2=450 3=600 4=710 5=1200   107H
                               ;6=2400 7=4800 8=9600 9=19200 default
BYTDLY: DB      5               ;0=0 delay  1=10ms  5=50 ms - 9=90 ms   108H
                               ;default time to send character in ter-
                               ;minal mode file transfer for slow BBS.
CRDLY:  DB      5               ;0=0 delay 1=100 ms 5=500 ms - 9=900 ms 109H
                               ;default time for extra wait after CRLF
                               ;in terminal mode file transfer
COLUMS: DB      5               ;number of DIR columns shown            10AH
SETFLG: DB      YES             ;yes=user-added Setup routine           10BH
SCRTST: DB      YES             ;Cursor control routine                 10CH
       DB      YES             ;yes=resend a record after any non-ACK  10DH
                               ;no=resend a record after a valid-NAK
BAKFLG: DB      NO              ;yes=change any file same name to .BAK  10EH
CRCDFL: DB      YES             ;yes=default to CRC checking            10FH
TOGCRC: DB      YES             ;yes=allow toggling of CRC to Checksum  110H
CVTBS:  DB      NO              ;yes=convert backspace to rub           111H
TOGLBK: DB      YES             ;yes=allow toggling of bksp to rub      112H
ADDLF:  DB      NO              ;no=no LF after CR to send file in      113H
                               ;terminal mode (added by remote echo)
TOGLF:  DB      YES             ;yes=allow toggling of LF after CR      114H
       DB      YES             ;yes=allow transmission of logon        115H
                               ;write logon sequence at location LOGON
SAVCCP: DB      YES             ;yes=do not overwrite CCP               116H
       DB      NO              ;yes=local command if EXTCHR precedes   117H
                               ;no=external command if EXTCHR precedes
       DB      YES             ;yes=allow toggling of LOCONEXTCHR      118H
LSTTST: DB      YES             ;yes=printer available on printer port  119H
XOFTST: DB      NO              ;yes=checks for XOFF from remote while  11AH
                               ;sending a file in terminal mode
XONWT:  DB      NO              ;yes=wait for XON after CR while        11BH
                               ;sending a file in terminal mode
TOGXOF: DB      YES             ;yes=allow toggling of XOFF checking    11CH
IGNCTL: DB      YES             ;yes=CTL-chars above ^M not displayed   11DH
EXTRA1: DB      0               ;for future expansion                   11EH
EXITCHR DB      'E'-40H         ;^E = Exit to main menu                 11FH
BRKCHR: DB      '@'-40H         ;^@ = Send 300 ms. break tone           120H
NOCONN: DB      'N'-40H         ;^N = Disconnect from the phone line    121H
LOGCHR: DB      'L'-40H         ;^L = Send logon                        122H
LSTCHR: DB      'P'-40H         ;^P = Toggle printer                    123H
UNSAVE: DB      'R'-40H         ;^R = Close input text buffer           124H
TRNCHR: DB      'T'-40H         ;^T = Transmit file to remote           125H
SAVCHR: DB      'Y'-40H         ;^Y = Open input text buffer            126H
EXTCHR: DB      '^'-40H         ;^^ = Send next character               127H
       DS      2               ;unused by MEX                          128H
;
INCTL1: JMP     INSP            ;go input status port                   12AH
       DS      7
;
OTDATA: JMP     OUTDP           ;go output data port                    134H
       DS      7
;
INPORT: JMP     INDP            ;go input data port                     13EH
       DS      7
;
MASKR:  ANI     dr      ! RET   ;bit to test for receive ready          148H
TESTR:  CPI     dr      ! RET   ;value of rcv. bit when ready           14BH
MASKS:  ANI     thre    ! RET   ;bit to test for send ready             14EH
TESTS:  CPI     thre    ! RET   ;value of send bit when ready           151H
       DS      12              ;                                       156H
;
;
       DS      2               ;for log on msg pointer
       DS      3               ;DIALV: not done here (maybe MXO-SM)    162H
DISCV:  JMP     DISCON          ;disconnect
GOODBV: JMP     GOODBY          ;                                       168H
INMODV: JMP     NITMOD          ;go to user written routine             16BH
NEWBDV: JMP     PBAUD           ;                                       16EH
       RET ! NOP ! NOP         ;NOPARV                                 171H
       RET ! NOP ! NOP         ;PARITV                                 174H
SETUPV: JMP     SETCMD          ;                                       177H
       DS      3               ;not used by MEX                        17AH
VERSNV: JMP     SYSVER          ;                                       17DH
BREAKV: JMP     SBREAK          ;                                       180H
;
; Do not change the following six lines (they provide access to routines
; in MEX that are present to support MDM7 overlays -- they will likely
; be gone by MEX v2.0).
;
ILPRTV: DS      3               ;                                       183H
INBUFV  DS      3               ;                                       186H
ILCMPV: DS      3               ;                                       189H
INMDMV: DS      3               ;                                       18CH
       DS      3               ;                                       18FH
TIMERV  DS      3               ;                                       192H
;
; Routine to clear to end of screen.  If using CLREOS and CLRSCRN, set
; SCRTEST to YES at 010AH (above).
;
CLREOS: LXI     D,EOSMSG        ;                                       195H
       MVI     C,PRINT
       CALL    MEX
       RET
;
CLS:    LXI     D,CLSMSG        ;                                       19EH
       MVI     C,PRINT
       CALL    MEX
       RET
;                                                                       1A7H
;
; end of fixed area
;
SYSVER: MVI     C,ILP           ;in-line print
       CALL    MEX
;
       IF MORMIO
;
       DB      'Morrow Multi I/O at 0F8H  V.'
;
       ENDIF
;
       IF NOT MORMIO
;
       DB      'Version for 8250 ACE  V.'
;
       ENDIF
;
       DB      REV/10+'0'
       DB      '.'
       DB      REV MOD 10+'0'
       DB      CR,LF
;
       IF SMDM
;
       DB      'with Hayes Smartmodem 1200',CR,LF,LF
;
       ENDIF

       DB      0
;
       MVI     C,ILP
       CALL    MEX
       DB      'Defaults-  ',0
       JMP     TELL
;
; Routine to exit just prior to exit-to-cpm
;
GOODBY: RET                     ;not done here
;
; Send break to remote
;
SBREAK: MVI     A,sbrk          ;send break for 300ms
       CALL    OUTCP
       PUSH    B
       MVI     B,3
       MVI     C,TIMER
       CALL    MEX
       POP     B
       MVI     A,wls0+wls1     ;reset to normal 8 bits, 1 stop, dlab off
       CALL    OUTCP
       RET
;
; Disconnect the modem
;
DISCON: XRA     A               ;turn off DTR
       CALL    OUTMP
       PUSH    B
       MVI     B,10            ;turn off DTR for 1000 ms.(my smartmodem
       MVI     C,TIMER         ;seems to require more than 300ms to hang up)
       CALL    MEX
       POP     B
       MVI     A,dtr           ;turn DTR back on
       CALL    OUTMP
       RET
;
; Initialize the port with default baud rate(1200)
;
NITMOD: PUSH    H
       PUSH    D
       PUSH    B
NITMO1: MVI     A,5             ;default to 1200 baud
       STA     MSPEED
       CALL    SELGRP          ;select morrow group
       XRA     A               ;disable 8250 interrupts
       OUT     MODIER          ;interrupt enable register
       MVI     A,wls0+wls1+dlab ;8 bit word, 1 stop, baud rate div on
       out     MODLCR

LSBSPD: MVI     A,60H           ;default 'LSB' for 1200 baud
       OUT     LBAUDP          ;register for 'LSB' when dlab=1

MSBSPD: MVI     A,00H           ;default 'MSB' for 1200 baud
       OUT     MBAUDP          ;register for 'MSB' when dlab=1
;
; finish up
;
       MVI     A,wls0+wls1     ;8 bit, 1 stop, turn dlab off
       out     MODLCR
       MVI     A,dtr           ;Be sure DTR is on
       out     MODMCR
;
       IF      SMDM
;
; for smartmodem only, send AT to set modem baudrate.

       LXI     H,SMSET
       CALL    SMSEND
SMCLR   MVI     C,INMDM
       CALL    MEX
       JNC     SMCLR

       ENDIF

       ORA     A               ;no errors, clear carry for return to STBAUD
       POP     B
       POP     D
       POP     H
       RET
;
       IF SMDM
;
SMSEND: MVI     C,SNDRDY        ;WAIT FOR MODEM READY
       CALL    MEX
       JNZ     SMSEND
       MOV     A,M             ;FETCH NEXT CHARACTER
       INX     H
       ORA     A               ;END?
       RZ                      ;DONE IF SO
       MOV     B,A             ;NO, POSITION FOR SENDING
       MVI     C,SNDCHR        ;NOPE, SEND THE CHARACTER
       CALL    MEX
       JMP     SMSEND
;
SMSET:  DB      'AT',CR,0       ;kick the modem
;
       ENDIF
;
; SET command: select baud rate, port number. Port number may be any of
; 1,2,, or 3, baud rate any of 110, 300, 450, 600, 1200, 2400, 4800
; 9600, 19200.  Special set-port syntax allows baud rate after port
; number.  Examples:
;
;       SET PORT 1
;       SET PORT 2 1200
;       SET PORT 3 300
;       SET BAUD 9600
;
SETCMD: MVI     C,SBLANK        ;any arguments?
       CALL    MEX
       JC      TELL            ;if not, go display port/baud
       LXI     D,CMDTBL
       MVI     C,LOOKUP
       CALL    MEX             ;parse argument
       PUSH    H               ;save any parsed argument adrs on stack
       RNC                     ;if we have one, return to it
       POP     H               ;oops, input not found in table
SETERR: MVI     C,ILP           ;inline print
       CALL    MEX
       DB      CR,LF,'SET command error',CR,LF,0
       RET
;
; Argument table
;
CMDTBL: DB      '?'+80H         ;help
       DW      STHELP
       DB      'BAU','D'+80H   ;"set baud"
       DW      STBAUD
;
       IF      MORMIO
;
       DB      'POR','T'+80H   ;"set port"
       DW      SETPOR
;
       ENDIF
;
       DB      0               ;<<=== table terminator
;
; "SET ?" processor
;
STHELP: MVI     C,ILP           ;inline print
       CALL    MEX
       DB      CR,LF,'SET BAUD <rate>'
;
       IF MORMIO
;
       DB      CR,LF,'SET PORT <port-number>'
       DB      CR,LF,'SET PORT <port-number> <baud-rate>'
;
       ENDIF
;
       DB      CR,LF,'Baud rate is one of:'
       DB      CR,LF,'  110 300 450 600 1200 2400 4800 9600 19200'
;
       IF      MORMIO
;
       DB      CR,LF,'Port number is one of:'
       DB      CR,LF,'  1, 2, or 3 for Morrow Multi I/O'
;
       ENDIF
;
       DB      CR,LF,0         ;end of message
       RET
;
; "SET BAUD" processor
;
STBAUD: MVI     C,BDPARS        ;function code: parse a baudrate
       CALL    MEX             ;let MEX look up code
       JC      BDERR           ;jump if invalid code
       CALL    PBAUD           ;no, try to set it
       JC      BDERR           ;if not one of ours, bomb out
       JMP     TELL            ;show the settings
;
BDERR:  MVI     C,ILP
       CALL    MEX
       DB      'Invalid baud rate selected',cr,lf,0
       RET
;
       IF      MORMIO
;
; SET PORT processor
;
SETPOR: MVI     C,SBLANK        ;scan to argument
       CALL    MEX
       JC      SETERR          ;if no arg, bomb out
       MVI     C,GNC           ;else consume it
       CALL    MEX
       SUI     '0'             ;convert
       CPI     0
       JZ      PRTERR          ;less than 1
       CPI     3+1
       JNC     PRTERR          ;more than 3
       STA     PORTS
       MVI     C,SBLANK        ;any thing more?
       CALL    MEX
       JNC     STBAUD          ;if so, go parse as baud rate
;
       ENDIF
;
TELL:
;
       IF      MORMIO
;
       MVI     C,ILP
       CALL    MEX
       DB      'Port: ',0
       LDA     PORTS
       ADI     '0'             ;get port # in ASCII
       STA     PORTAS
       MVI     C,ILP
       CALL    MEX
PORTAS: DB      ' ,  ',0
;
       ENDIF
;
       MVI     C,ILP           ;inline print
       CALL    MEX             ;display baud
       DB      'Baud: ',0
       LDA     MSPEED          ;get current baud rate
       MVI     C,PRBAUD        ;let MEX print it
       CALL    MEX
       RET
;
PRTERR: MVI     C,ILP
       CALL    MEX
       DB      'Invalid port selected',CR,LF,0
       RET



; This routine sets baud rate passed as MSPEED code in A.
; Returns CY=1 if baud rate not supported (if supported,
; this routine must set the new MSPEED code).
;
PBAUD:  PUSH    H               ;don't alter anybody
       PUSH    D
       PUSH    B
       MOV     E,A             ;MSPEED code to DE
       MVI     D,0
       LXI     H,BAUDTB        ;offset into table
       DAD     D
       DAD     D               ;each entry two bytes
       MOV     A,M             ;get LSB
       ORA     A               ;0? (means unsupported code)
       STC                     ;prep carry in case unsupported
       JZ      PBEXIT          ;exit if bad
       MOV     A,E             ;get MSPEED back
       STA     NITMO1+1        ;store in NITMOD for execution
       MOV     A,M             ;get LSB of baud rate divisor
       STA     LSBSPD+1        ;store in NITMOD for execution
       INX     H               ;bump to MSB
       MOV     A,M             ;get it
       STA     MSBSPD+1        ;store it
       JMP     NITMO1          ;go initialize the port/modem,
;                                carry reset there
;
PBEXIT: POP     B
       POP     D
       POP     H
       RET
;
BAUDTB: DW      BD110,BD300,BD450,BD600,BD710
       DW      BD1200,BD2400,BD4800,BD9600,BD19200
;
;       Port access routines
;
; Input
;
INSP:   CALL    SELGRP          ;select morrow group
       IN      MODLSR          ;get the status
       RET

INDP:   CALL    SELGRP          ;select morrow group
       IN      MODDAT          ;get the char
       RET
;
; Output
;
OUTDP:  PUSH    PSW             ;save the character
       CALL    SELGRP          ;select group
       POP     PSW             ;get char back
       OUT     MODDAT          ;and send it
       RET

OUTMP:  PUSH    PSW             ;save A
       CALL    SELGRP          ;select group
       POP     PSW             ;get A back
       OUT     MODMCR          ;send it to modem control register
       RET

OUTCP:  PUSH    PSW             ;save A
       CALL    SELGRP          ;select group
       POP     PSW             ;get A back
       OUT     MODLCR          ;send it to line control reg
       RET

; Select Morrow Multi I/O group(port)
;
SELGRP:
;
       IF MORMIO
;
       LDA     PORTS
       OUT     GPORT           ;select Morrow group #
;
       ENDIF
;
       RET
;
       IF      MORMIO
;
PORTS:  DB      MPORT           ;default modem group(port)
;
       ENDIF
;
; Clear-to-end-of-screen and clear-screen sequences(H/Z 19)
;
EOSMSG: DB      ESC,'J','$'
CLSMSG: DB      ESC,'E','$'
;
;
       END