;
; MSXMBC - MS-DOS KERMIT MODULE FOR SANYO MBC-55x
;
;       THIS MODULE WAS CREATED BY EDITING THE GENERIC MS-DOS MODULE
; MSXGEN AND ADDING THE SANYO SPECIFIC CODE TO PERFORM THE NEEDED
; FUNCTIONS, MANY OF WHICH WERE GRACEFULLY BORROWED FROM THE MSXIBM
; MODULE. PLEASE NOTE THAT THE SANYO "AUX" DEVICE HARDWARE CONSISTS OF:
;
;               8251A   SERIAL COMMUNICATIONS DEVICE (DOES RS-232 STUFF)
;               8259A   SYSTEM INTERRUPT CONTROLLER
;               8253    TIMER DEVICE (FED TO 8251A AS BAUD RATE)
;
; DEFUALT SETTINGS ARE:
;
;               BAUD RATE       = 300
;               CHAR LENGTH     = 8 BITS
;               PARITY          = NONE
;               STOP BITS       = 1
;
; JOE SMILEY 1-5-85
;
; Add global entry point vtstat for use by Status in mssset.
; Joe R. Doupnik 12 March 1986

        ;
        ; GLOBALLY ACCESSIBLE SUBROUTINES
        ;
        PUBLIC  SERINI                  ; INITIALIZE AUX DEVICE FOR INPUT
        PUBLIC  SERRST                  ; RESTORE AUX DEVICE TO CALM STATE
        PUBLIC  CLRBUF                  ; CLEAR AUX DEVICE INPUT BUFFERS
        PUBLIC  OUTCHR                  ; OUTPUT CHARACTER ON AUX DEVICE
        PUBLIC  COMS                    ; SET COMM PORT (ONLY ONE ON SANYO)
        PUBLIC  VTS                     ; HEATH-19 NOT IMPLEMENTED
        PUBLIC  DODEL                   ; DELETE CHARACTER FROM SCREEN
        PUBLIC  CTLU                    ; ERASE CURRENT LINE
        PUBLIC  CMBLNK                  ; BLANK THE ENTIRE VIDEO SCREEN
        PUBLIC  LOCATE                  ; HOME CURSOR
        PUBLIC  LCLINI                  ; LOCAL SYSTEM INITIALIZATION
        PUBLIC  PRTCHR                  ; GET A CHARACTER (IF ONE) FROM AUX
        PUBLIC  DOBAUD                  ; SET AUX DEVICE BAUD RATE
        PUBLIC  CLEARL                  ; CLEAR A LINE ON VIDEO SCREEN
        PUBLIC  DODISK                  ; GET NO. OF SYSTEM DISK DRIVES
        PUBLIC  GETBAUD                 ; GET DEFAULT BAUD RATE
        PUBLIC  BEEP                    ; OUTPUT BEEP ON PC
        PUBLIC  PUTHLP                  ; DISPLAY HELP MESSAGE ON SCREEN
        PUBLIC  PUTMOD                  ; PUT MODE STRING ON LINE 24
        PUBLIC  CLRMOD                  ; CLEAR MODE LINE
        PUBLIC  POSCUR                  ; POSITION CURSOR ON VIDEO SCREEN
        PUBLIC  SENDBR                  ; SEND BREAK SIGNAL ON AUX DEVICE
        PUBLIC  TERM                    ; PERFORM TERMINAL EMULATION
        PUBLIC  SHOWKEY                 ; NOT IMPLEMENTED
        public  vtstat                  ; Status for mssset. [jrd]
        ;
        ; GLOBALLY ACCESSIBLE DATA
        ;
        PUBLIC  COUNT                   ; NO. OF CHARACTERS IN INPUT BUFFER
        PUBLIC  XOFSNT                  ; FLAG INDICATING XOFF SENT OUT AUX
        PUBLIC  MACHNAM                 ; ASCII STRING CONTAINING MACHINE NAME
        PUBLIC  SETKTAB                 ; NOT USED
        PUBLIC  SETKHLP                 ; NOT USED

;
; INCLUDE STANDARD MS-DOS DEFINITIONS
;
        INCLUDE MSSDEF.H

;
; ADDITIONAL EQUATES
;
FALSE   EQU     0                       ; BOOLEAN FALSE VALUE
TRUE    EQU     1                       ; BOOLEAN TRUE VALUE
MNTRGH  EQU     (BUFSIZ * 3) / 4        ; HIGH POINT OF BUFFER FULL
VIDEO   EQU     010H                    ; VIDEO INTERRUPT

;
; EXTERNAL VARIABLES USED
;
;       DRIVES  - NO. OF DISK DRIVES ON SYSTEM
;       FLAGS   - GLOBAL FLAGS AS PER FLGINFO STRUCTURE
;       PORTVAL - POINTER TO CURRENT PORTINFO STRUCTURE (ALWAYS PORT1)
;       PORT1   - PORTINFO STRUCTURE USED FOR SANYO
;

;
; DEFINE DATA SEGMENT
;
DATAS   SEGMENT PUBLIC  'DATAS'
        EXTRN   DRIVES:BYTE             ; NO. OF DISK DRIVES ON SYSTEM
        EXTRN   FLAGS:BYTE              ; GLOBAL FLAGS USED
        EXTRN   PORTVAL:WORD            ; POINTER TO PORTINFO STRUCTURE
        EXTRN   PORT1:BYTE              ; PORTINFO STRUCTURE USED BY SANYO

;
; SANYO DEVICE DEFINITIONS (AND BAUD RATE TABLE)
;

;
; 8251A serial communications device
;
        BUF8251 EQU     028H            ; I/O address of 8251A in/out buffer
        CMD8251 EQU     02aH            ; I/O address of 8251A command buffer
        STS8251 EQU     02aH            ; I/O address of 8251A status buffer
        VEC8251 EQU     03e8H           ; 8251A interrupt vector location
        INT8251 EQU     0fbH            ; 8259A interrupt enable mask (int 2)
;
; 8251A Command Intruction Formats
;
        TxEN    EQU     001H            ; 8251A transmit enable
        DTR     EQU     002H            ; 8251A data terminal ready high
        RxEN    EQU     004H            ; 8251A receiver enable
        SBRK    EQU     008H            ; 8251A send break character
        ER      EQU     010H            ; 8251A error reset (must when RxEN)
        RTS     EQU     020H            ; 8251A request to send high
        IR      EQU     040H            ; 8251A internal reset
;
; 8251A Status Read Formats
;
        TxRDY   EQU     001H            ; 8251A transmitter ready
        RxRDY   EQU     002H            ; 8251A receiver ready
        TxEMPTY EQU     004H            ; 8251A transmit buffer empty
        PE      EQU     008H            ; 8251A parity error
        OE      EQU     010H            ; 8251A overrun error
        FE      EQU     020H            ; 8251A framing error
        BRKDET  EQU     040H            ; 8251A break detect
        DSR     EQU     080H            ; 8251A data set ready at zero level

;
; 8253 timer device
;
        CKA8253 EQU     020H            ; I/O address of 8253 counter #0
        CKB8253 EQU     022H            ; I/O address of 8253 counter #1
        CKC8253 EQU     024H            ; I/O address of 8253 counter #2
        CMD8253 EQU     026H            ; I/O address of 8253 command buffer
;
; 8253 Timer baud rate tables
;
; Note:
;       the 8251a is normally (by default) set up to a clock multiplier
; of 16x rather than 1x or 64x.  this is OK for most of the popular baud
; rates, however, the values programmed below may not work for some of the
; less popular rates without resetting the clock multiplier on the 8251a,
; and reprogramming the timer values below.
;
;       in other words, i was too lazy to verify that all of the timer
; values mentioned below would work for the specified baud rates.
;
BDDAT   LABEL   WORD
        DW      (29829/((45/30)*8))     ; Timer value for baud rate 45.5
        DW      (29829/((50/30)*8))     ; Timer value for baud rate 50
        DW      (29829/((75/30)*8))     ; Timer value for baud rate 75
        DW      (29829/((110/30)*8))    ; Timer value for baud rate 110
        DW      (29829/((134/30)*8))    ; Timer value for baud rate 134.5
        DW      (29829/((150/30)*8))    ; Timer value for baud rate 150
        DW      (29829/((300/30)*8))    ; Timer value for baud rate 300
        DW      (29829/((600/30)*8))    ; Timer value for baud rate 600
        DW      (29829/((1200/30)*8))   ; Timer value for baud rate 1200
        DW      (29829/((1800/30)*8))   ; Timer value for baud rate 1800
        DW      (29829/((2000/30)*8))   ; Timer value for baud rate 2000
        DW      (29829/((2400/30)*8))   ; Timer value for baud rate 2400
        DW      (29829/((4800/30)*8))   ; Timer value for baud rate 4800
        DW      (29829/((9600/30)*8))   ; Timer value for baud rate 9600
        DW      (29829/((19200/30)*8))  ; Timer value for baud rate 19200
        DW      (29829/((38400/30)*8))  ; Timer value for baud rate 38400

;
; 8259A interrupt controller
;
        CMA8259 EQU     000H            ; I/O address of 8259A command buff 1
        CMB8259 EQU     002H            ; I/O address of 8259A command buff 2

;
; ASCII MESSAGES
;
MACHNAM DB      'Sanyo MBC-55x MS-DOS v2.11$'
ERMS20  DB      CR,LF,'?Warning: System has no disk drives$'
ERMS40  DB      CR,LF,'?Warning: Unrecognized baud rate$'
BADBD   DB      CR,LF,'Unimplemented baud rate$'
NOIMP   DB      CR,LF,'Command not implemented.$'
SHKMSG  DB      'Not implemented.'
SHKLEN  EQU     $-SHKMSG
SETKTAB DB      0
SETKHLP DB      0
DELSTR  DB      BS,' ',BS,'$'
CLRLIN  DB      CR,'$'
RBTRN   DB      7FH                     ; RUBOUT CODE

;
; ADDITIONAL DATA STRUCTURES
;
TELFLG  DB      0                       ; TERMINAL EMULATION FLAG
XOFSNT  DB      0                       ; XOFF JUST SENT FLAG
XOFRCV  DB      0                       ; XOFF JUST RECEIVED FLAG
PORTIN  DB      0                       ; AUX PORT INITIALIZED FLAG

SAVSCI  DW      ?                       ; SAVED AUX PORT INTERRUPT VECTOR
SAVSCS  DW      ?                       ; SAVED AUX PORT INTERRUPT VECTOR

SOURCE  DB      BUFSIZ DUP(?)           ; INPUT DATA BUFFER (FROM AUX)
SRCPNT  DW      0                       ; INPUT BUFFER POINTER
COUNT   DW      0                       ; NO. OF CHARACTERS IN BUFFER
SAVESI  DW      0                       ; SAVE SI REGISTER HERE

OURARG  TERMARG <>                      ; TERMINAL EMULATOR ARG STORAGE

DATAS   ENDS                            ; END OD DATA SEGMENT

;
; START OF CODE SEGMENT
;
CODE    SEGMENT PUBLIC
        EXTRN   DEFKEY:NEAR             ; DEFINE A TRANSLATION ROUTINE
        EXTRN   PRSERR:NEAR             ; EXTERNAL PRINT ERROR ROUTINE
        ASSUME  CS:CODE, DS:DATAS       ; ASSUME CODE AND DATA SEGMENTS

;
; DODISK - SET THE NUMBER OF DISK DRIVES ON THE HOST SYSTEM
;
; OUTPUTS:
;       DRIVES  - GLOBAL BYTE VARIABLE SET TO THE NUMBER OF DISK DRIVES
;
; NOTES:
;       RETURNS NORMALLY.
;
DODISK  PROC    NEAR
        MOV     AH,GCURDSK              ; SET CODE TO GET CURRENT DISK DRIVE
        INT     DOS                     ; GET THE CURRENT DISK DRIVE
        MOV     DL,AL                   ; SET CURRENT DISK DRIVE
        MOV     AH,SELDSK               ; SET CODE TO SELECT CURRENT DISK
        INT     DOS                     ; SELECT AND GET NO. OF DRIVES
        MOV     DRIVES,AL               ; SET GLOBAL VARIABLE
        RET                             ; AND RETURN
DODISK  ENDP

;
; CLRBUF - CLEAR 8251A (AUX DEVICE) INPUT BUFFER
;
;       THIS ROUTINE CLEARS THE AUX DEVICE INPUT BUFFER SO THAT NO
; ACCUMULATED CHARACTERS (ESPECIALLY IMPORTANT WHEN TALKING TO
; SERVER KERMITS) INTEREFER WITH COMMUNICATION. IT ALSO SETS UP THE
; CIRCULAR INPUT BUFFER USED BY THE INPUT INTERRUPT ROUTINE.
;
; NOTES:
;       THIS ROUTINE RETURNS NORMALLY.
;
CLRBUF  PROC    NEAR
        PUSHF                           ; SAVE FLAGS
        CLI                             ; LOCK OUT INTERRUPTS
        PUSH    AX                      ;;; SAVE REGISTER
        IN      AL,STS8251              ;;; READ STATUS REGISTER
        IN      AL,BUF8251              ;;; READ INPUT BUFFER
        IN      AL,BUF8251              ;;; READ AGAIN (DOUBLE BUFFERED INPUT)
        MOV     AX,OFFSET SOURCE        ;;; GET START OF INPUT DATA BUFFER
        ;
        ; RESET CIRCULAR INPUT BUFFER POINTERS AND COUNT
        ;
        MOV     SRCPNT,AX               ;;; SET DATA BUFFER POINTER
        MOV     SAVESI,AX               ;;; AND SET INITIAL SI POINTER
        MOV     COUNT,0                 ;;; INITIALIZE NO. OF CHARS IN BUFFER
        POP     AX                      ;;; RESTORE REGISTER
        POPF                            ;;; RESTORE FLAGS (RE-ENABLE INTS)
        RET                             ; RETURN
CLRBUF  ENDP

;
; CLEARL - CLEAR TO THE END OF THE CURRENT LINE ON THE VIDEO SCREEN
;
CLEARL  PROC    NEAR
        MOV     AH,3                    ; SET CODE TO GET CURSOR POSITION
        MOV     BH,0                    ; SET PAGE 0
        INT     VIDEO                   ; GET CURRENT CURSOR POSITION
        MOV     CX,DX                   ; COPY CURSOR POSITION
        MOV     DL,79                   ; SET COLUMN POSITION OF SCROLL
        MOV     AH,7                    ; SET CODE TO SCROLL PAGE DOWN
        MOV     AL,0                    ; SET NUMBER OF LINES (WHOLE WINDOW)
        MOV     BH,7                    ; BLANK LINE ATTRIBUTE
        INT     VIDEO                   ; AND NOW BLANK THE LINES
        RET                             ; AND RETURN
CLEARL  ENDP

;
; OUTCHR - OUTPUT CHARACTER TO AUX DEVICE DOING FLOW CONTROL
;
;       THIS SUBROUTINE WILL OUTPUT THE SPECIFIED CHARACTER ON THE AUX
; DEVICE WHILE HONORING XON/XOFF FLOW CONTROL.
;
; INPUTS:
;       AH      - CONTAINS CHARACTER TO BE OUTPUT
;
; NOTES:
;       THIS ROUTINE SKIPS RETURN ON SUCCESS.
;
OUTCHR: MOV     BP,PORTVAL              ; GET POINTER TO CURRENT PORT STRUCTURE
        CMP     DS:[BP].FLOFLG,FALSE    ; DOING FLOW CONTROL?
        JE      OUTCH2                  ; IF E NO, JUST CONTINUE
        XOR     CX,CX                   ; CLEAR COUNTER REGISTER
OUTCH1: CMP     XOFRCV,TRUE             ; CURRENTLY BEING HELD?
        JNE     OUTCH2                  ; IF NE NO, OK TO PROCEED
        LOOP    OUTCH1                  ; ELSE WAIT A WHILE
        MOV     XOFRCV,FALSE            ; TIMED OUT, FORCE XOFF OFF AND GO ON
        ;
        ; OUTCH2 - OUTPUT CHARACTER TO AUX DEVICE
        ;
        ; NOTES:
        ;       - DESTROYS CONTENTS OF AX REGISTER
        ;       - 8251A DEVICE HANDLES PARITY IN HARDWARE (SEE SETUP BELOW)
        ;
OUTCH2: PUSHF                           ; SAVE FLAGS
        CLI                             ; LOCK OUT INTERRUPTS
        PUSH    AX                      ;;; SAVE REGISTER
        MOV     AL,(TxEN+DTR+RxEN+ER+RTS) ;;; GET OUTPUT ENABLE COMMAND
        OUT     CMD8251,AL              ;;; COMMAND 8251 FOR OUTPUT
        CALL    DUMRET                  ;;; KILL SOME TIME
OUTCH3: IN      AL,STS8251              ;;; READ DEVICE STATUS
        TEST    AL,TxRDY                ;;; TRANSMITTER READY?
        JZ      OUTCH3                  ;;; IF ZERO NO
        POP     AX                      ;;; RESTORE REGISTER
        MOV     AL,AH                   ;;; GET CHARACTER TO OUTPUT
        OUT     BUF8251,AL              ;;; OUTPUT CHARACTER
        CALL    DUMRET                  ;;; KILL SOME TIME
        MOV     AL,(DTR+RxEN+ER+RTS)    ;;; GET INPUT ENABLE COMMAND
        OUT     CMD8251,AL              ;;; RE-COMMAND 8251A FOR INPUT
        POPF                            ;;; RESTORE FLAGS (RE-ENABLE INTS)
        JMP     RSKP                    ; RETURN
DUMRET: RET                             ; DUMMY RETURN

;
; CMBLNK - BLANK THE VIDEO SCREEN
;
; NOTES:
;       RETURN NORMALLY.
;
CMBLNK  PROC    NEAR
        MOV     CX,0                    ; SET HOME POSITION
        MOV     DX,0184FH               ; SET LOWER RIGHT CORNER OF SCREEN
        MOV     BH,7                    ; SET BLANK ATTRIBUTE
        MOV     AX,0600H                ; SET CODE FOR SCROLL PAGE UP
        INT     VIDEO                   ; AND CLEAR THE SCREEN
        RET                             ; AND RETURN
CMBLNK  ENDP

;
; LOCATE - HOME THE CURSOR
;
; NOTES:
;       RETURNS NORMALLY.
;
LOCATE  PROC    NEAR
        MOV     DX,0                    ; SET HOME POSITION
        JMP     POSCUR                  ; AND GO TO POSITION
LOCATE  ENDP

;
; PUTMOD - WRITE A LINE AT THE BOTTOM OF THE VIDEO SCREEN
;
; INPUTS:
;       DX      - ADDRESS OF LINE, TERMINATED BY '$'
;
; NOTES:
;       RETURNS NORMALLY.
;
PUTMOD  PROC    NEAR
        PUSH    DX                      ; SAVE REGISTER
        MOV     CX,01800H               ; SET START ADDRESS
        MOV     DX,0184FH               ; AND END ADDRESS
        MOV     AX,0600H                ; SET CODE TO SCROLL PAGE UP
        MOV     BH,07H                  ; SET ATTRIBUTE
        INT     VIDEO                   ; CLEAR LINE
        MOV     DX,01800H               ; RE-ADDRESS LINE 24
        CALL    POSCUR                  ; POSITION THE CURSOR
        POP     DX                      ; GET STRING ADDRESS
        MOV     AH,PRSTR                ; SET CODE TO PRINT STRING
        INT     DOS                     ; PRINT THE STRING
        RET                             ; AND RETURN
PUTMOD  ENDP

;
; CLRMOD - CLEAR THE LINE WRITTEN BY PUTMOD
;
; NOTES:
;       RETURNS NORMALLY.
;
CLRMOD  PROC    NEAR
        MOV     CX,01800H               ; ADDRESS START OF LINE 24
        MOV     DX,0184FH               ; AND END ADDRESS
        MOV     AX,0600H                ; SET CODE TO SCROLL PAGE UP
        MOV     BH,07H                  ; NORMAL ATTRIBUTE
        INT     VIDEO                   ; AND CLEAR LINE
        RET                             ; AND RETURN
CLRMOD  ENDP

;
; PUTHLP - PUT A HELP MESSAGE ON THE SCREEN
;
; INPUTS:
;       AX      - ADDRESS OF MESSAGE, TERMINATED BY NUL
;
; NOTES:
;       RETURNS NORMALLY.
;
PUTHLP  PROC    NEAR
        PUSH    AX                      ; SAVE THE STRING ADDRESS
        MOV     SI,AX                   ; SET STRING ADDRESS
        MOV     DH,1                    ; INITIALIZE COUNTER
PUTHL1: LODSB                           ; GET NEXT BYTE
        CMP     AL,LF                   ; GET A LINE FEED?
        JNE     PUTHL2                  ; IF NE NO, CONTINUE
        INC     DH                      ; ELSE COUNT IT
        JMP     PUTHL1                  ; AND CONTINUE
PUTHL2: CMP     AL,0                    ; AT END OF STRING?
        JNE     PUTHL1                  ; IF NE NO, CONTINUE COUNTING
        MOV     AX,0600H                ; SET CODE TO SCROLL ACTIVE PAGE UP
        XOR     CX,CX                   ; SET HOME POSITION
        MOV     DL,04FH                 ; TO BOTTOM RIGHT OF NEEDED PIECE
        MOV     BH,070H                 ; SET INVERSE VIDEO ATTRIBUTE
        INT     VIDEO                   ; CLEAR SCREEN AREA
        CALL    LOCATE                  ; HOME CURSOR
        POP     SI                      ; RESTORE STRING ADDRESS
PUTHL3: LODSB                           ; GET NEXT BYTE
        CMP     AL,0                    ; END OF STRING?
        JE      PUTHL4                  ; IF E YES
        MOV     AH,14                   ; SET CODE TO WRITE TO VIDEO
        INT     VIDEO                   ; AND DO IT
        JMP     PUTHL3                  ; AND DO NEXT CHARACTER
PUTHL4: MOV     DX,24 * 100H            ; SET ADDRESS OF LAST LINE
        JMP     POSCUR                  ; AND POSITION CURSOR THERE
PUTHLP  ENDP

;
; DOBAUD SET THE CURRENT BAUD RATE
;
; NOTES:
;       RETURNS NORMALLY.
;
DOBAUD  PROC    NEAR
        PUSH    AX                      ; SAVE REGISTER
        PUSH    BX                      ; SAVE REGISTER
        PUSH    BP                      ; SAVE REGISTER
        MOV     BP,PORTVAL              ; ADDRESS PORT STRUCTURE
        MOV     AX,DS:[BP].BAUD         ; GET BAUD RATE INDEX
        SHL     AX,1                    ; CONVERT TO WORD INDEX
        MOV     BX,AX                   ; RE-GET OFFSET ADDRESS
        ADD     BX,OFFSET BDDAT         ; ADD IN BASE ADDRESS OF TABLE
        ;
        ; SET TIMER VALUE FOR BAUD RATE GENERATION BY 8253 TIMER CHIP
        ;
        MOV     AX,[BX]                 ; GET 8253 TIME COUNT FOR THIS RATE
        OUT     CKC8253,AL              ; OUTPUT LOW BYTE OF VALUE
        MOV     AL,AH                   ; GET HIGH BYTE
        OUT     CKC8253,AL              ; OUTPUT HIGH BYTE OF VALUE
        POP     BP                      ; RESTORE REGISTER
        POP     BX                      ; RESTORE REGISTER
        POP     AX                      ; RETSORE REGISTER
        RET                             ; AND RETURN
DOBAUD  ENDP

;
; GETBAUD - SET DEFAULT BAUD RATE TO 300
;
GETBAUD PROC    NEAR
        PUSH    AX                      ; SAVE REGISTER
        PUSH    BP                      ; SAVE REGISTER
        MOV     AX,6                    ; GET INDEX FOR BAUD RATE OF 300
        MOV     BP,PORTVAL              ; GET PORT INFO STRUCTURE
        MOV     DS:[BP].BAUD,AX         ; SET INDEX
        POP     BP                      ; RESTORE REGISTER
        POP     AX                      ; RESTORE REGISTER
        RET
GETBAUD ENDP

;
; SERINI - SERIAL (AUX) DEVICE INITIALIZATION
;
;       THIS FUNCTION IS CALLED TO SET UP THE SERIAL DEVICE INPUT
; INTERRUPT AND INITIALIZE THE SERIAL DEVICE BEFORE COMMUNICATIONS.
; NOTE THAT THIS FUNCTION SHOULD BE ABLE TO BE CALLED TWICE IN
; SUCCESSION WITHOUT DISASTEROUS RESULTS.
;
;       "SERRST" IS THE OPPOSITE OF THIS FUNCTION AND SHOULD RETURN
; THE DEVICE TO A QUESCIENT STATE.
;
; NOTES:
;       THE AUX DEVICE IS SET UP BY DEFAULT FOR 300 BAUD, 8 BITS
; PER CHARACTER, 1 STOP BIT, AND NO PARITY.
;
;       THIS FUNCTION RETURNS NORMALLY.
;
SERINI  PROC    NEAR
        CMP     PORTIN,0                ; DEVICE ALREADY INITIALIZED?
        JNE     SERIN0                  ; IF NE YES
        ;
        ; RESET 8251A DEVICE AND SET DEFAULT OPERATING MODE
        ;
        CLI                             ; DISABLE INTERRUPTS
        MOV     AL,IR                   ;;; GET 8251A INTERNAL RESET COMMAND
        OUT     CMD8251,AL              ;;; RESET 8251A DEVICE
        CALL    DUMRET                  ;;; KILL SOME TIME
        MOV     AL,04EH                 ;;; GET MODE (8 BITS PER CHAR, NO
                                        ;;;  PARITY, 1 STOP BIT, 16X CLOCK)
        OUT     CMD8251,AL              ;;; SET OPERATING MODE ON 8251A
        CALL    DUMRET                  ;;; KILL SOME TIME
        MOV     AL,(DTR+RxEN+ER+RTS)    ;;; GET INPUT ENABLE COMMAND
        OUT     CMD8251,AL              ;;; ENABLE INPUT ON 8251A
        ;
        ; SET NEW INTERRUPT VECTOR AND UNMASK 8251A INTERRUPT LINE ON 8259A
        ;
        PUSH    ES                      ;;; SAVE SEGMENT REGISTER
        MOV     AX,0000                 ;;; GET SEGMENT OF VECTOR SPACE
        MOV     ES,AX                   ;;; SET SEGMENT ADDRESS
        MOV     BX,VEC8251              ;;; GET ADDRESS OF AUX INT VECTOR
        MOV     AX,ES:[BX]              ;;; GET OLD VECTOR OFFSET
        MOV     SAVSCI,AX               ;;; AND SAVE IT
        MOV     AX,OFFSET SERINT        ;;; GET NEW VECTOR OFFSET
        MOV     ES:[BX],AX              ;;; AND SET IT
        ADD     BX,2                    ;;; GET TO NEXT WORD IN VECTOR
        MOV     AX,ES:[BX]              ;;; AND GET IT
        MOV     SAVSCS,AX               ;;; AND SAVE SECOND WORD
        MOV     ES:[BX],CS              ;;; SET OUR SEGMENT ADDRESS
        IN      AL,CMB8259              ;;; GET CURRENT INTERRUPT MASK
        AND     AL,INT8251              ;;; UNMASK 8251A INTERRUPT
        OUT     CMB8259,AL              ;;; SET NEW MASK VALUE
        POP     ES                      ;;; RESTORE SEGMENT REGISTER
        ;
        ; CLEAR THE INPUT DEVICE AND SET UP CIRCULAR INPUT BUFFER
        ;
        CALL    CLRBUF                  ;;; CLEAR THE INPUT BUFFER
        CALL    DOBAUD                  ;;; SET BAUD RATE LOCALLY
        ;
        ; INITIALIZATION DONE.
        ;
        MOV     PORTIN,1                ;;; SET PORT IS INITIALIZED
        STI                             ;;; ENABLE INTERRUPTS
SERIN0: RET                             ; RETURN
SERINI  ENDP

;
; SERRST - RESTORE SERIAL PORT INTERRUPT
;
SERRST  PROC    NEAR
        CMP     PORTIN,0                ; NEED TO RESET?
        JE      SERRS0                  ; IF EQUAL NO
        CLI                             ; DISABLE INTERRUPTS
        PUSH    ES                      ;;; SAVE SEGMENT REGISTER
        MOV     AX,0000                 ;;; GET SEGMENT OF VECTOR SPACE
        MOV     ES,AX                   ;;; SET SEGMENT ADDRESS
        MOV     BX,VEC8251              ;;; GET ADDRESS OF AUX INT VECTOR
        MOV     AX,SAVSCI               ;;; GET OLD VECTOR OFFSET
        MOV     ES:[BX],AX              ;;; AND SET IT
        ADD     BX,2                    ;;; GET TO NEXT WORD IN VECTOR
        MOV     AX,SAVSCS               ;;; GET SECOND WORD SAVED
        MOV     ES:[BX],AX              ;;; SET OLD SEGMENT ADDRESS
        POP     ES                      ;;; RESTORE SEGMENT REGISTER
        STI                             ;;; RE-ENABLE INTERRUPTS
        MOV     PORTIN,0                ; SET DEVICE NOT INITIALIZED
SERRS0: RET                             ; RETURN
SERRST  ENDP

;
; SERINT - SERIAL PORT (AUX DEVICE) INPUT INTERRUPT SERVICE ROUTINE
;
SERINT  PROC  NEAR
        PUSH    AX                      ;;; SAVE REGISTER
        PUSH    BX                      ;;; SAVE REGISTER
        PUSH    CX                      ;;; SAVE REGISTER
        PUSH    DX                      ;;; SAVE REGISTER
        PUSH    DI                      ;;; SAVE REGISTER
        PUSH    BP                      ;;; SAVE FRAME POINTER
        PUSH    DS                      ;;; SAVE SEGMENT REGISTER
        PUSH    ES                      ;;; SAVE SEGMENT REGISTER
        CLD                             ;;; DO AUTO-INCREMENT ON STRINGS
        MOV     AX,SEG DATAS            ;;; GET DATA SEGEMENT ADDRESS
        MOV     DS,AX                   ;;; SET DATA SEGMENT ADDRESS
        MOV     ES,AX                   ;;; AND SET AS EXTRA SEGMENT
        MOV     DI,SRCPNT               ;;; GET POINTER TO INPUT DATA BUFFER
        IN      AL,STS8251              ;;; GET 8251A STATUS
        TEST    AL,RxRDY                ;;; RECEIVER READY (GOT A CHARACTER)?
        JZ      RETINT                  ;;; IF Z NO
        IN      AL,BUF8251              ;;; ELSE GET CHARACTER INPUT
        CMP     TELFLG,0                ;;; TERMINAL EMULATION MODE?
        JZ      SRINT0                  ;;; IF Z NO
        AND     AL,07FH                 ;;; ELSE TERMINAL MODE 7 BITS ONLY
SRINT0: OR      AL,AL                   ;;; IS THIS A NUL CHARACTER?
        JZ      RETINT                  ;;; IF Z YES, IGNORE NULS
        CMP     AL,07FH                 ;;; CHARACTER A RUBOUT?
        JZ      RETINT                  ;;; IF Z YES, IGNORE THEM TOO
        MOV     BP,PORTVAL              ;;; GET ADDRESS OF PORT STRUCTURE
        CMP     DS:[BP].FLOFLG,0        ;;; ARE WE DOING FLOW CONTROL?
        JE      SRINT2                  ;;; IF E NO
        MOV     BX,DS:[BP].FLOWC        ;;; FLOW CONTROL (BH = XON, BL = XOFF)
        CMP     AL,BL                   ;;; IS INPUT CHARACTER AN XOFF?
        JNE     SRINT1                  ;;; IF NE NO, SO CONTINUE
        MOV     XOFRCV,TRUE             ;;; SET RECEIVED XOFF
        JMP     RETINT                  ;;; AND EXIT FOR NOW
SRINT1: CMP     AL,BH                   ;;; GET AN XON?
        JNE     SRINT2                  ;;; IF NE NO, CONTINUE
        MOV     XOFRCV,FALSE            ;;; CANCEL XOFF
        JMP     RETINT                  ;;; AND EXIT INTERRUPT
SRINT2: STOSB                           ;;; STORE CHARACTER IN BUFFER
        CMP     DI,OFFSET SOURCE + BUFSIZ ;;; TIME TO WRAP BUFFER BACK TO START
        JB      SRINT3                  ;;; IF B NO
        MOV     DI,OFFSET SOURCE        ;;; ELSE WRAP BUFFER BACK TO START
SRINT3: INC     COUNT                   ;;; COUNT CHARACTER INPUT
        CMP     DS:[BP].FLOFLG,0        ;;; DOING FLOW CONTROL?
        JE      RETINT                  ;;; IF E NO, JUST LEAVE INTERRUPT
        CMP     XOFSNT,TRUE             ;;; HAVE WE SENT AN XOFF?
        JE      RETINT                  ;;; IF E YES, JUST EXIT
        CMP     COUNT,MNTRGH            ;;; PAST THE HIGH TRIGGER POINT?
        JBE     RETINT                  ;;; IF BE NO, WITHIN LIMIT
        MOV     AH,BL                   ;;; GET THE XOFF CHARACTER
        CALL    OUTCHR                  ;;; AND SEND IT
        NOP                             ;;; ALLOW FOR RSKP RETURN ON ERROR
        NOP                             ;;;     "
        NOP                             ;;;     "
        MOV     XOFSNT,TRUE             ;;; SET SENT XOFF CHARACTER
RETINT: MOV     SRCPNT,DI               ;;; SAVE UPDATED BUFFER POINTER
        POP     ES                      ;;; RESTORE SEGMENT REGISTER
        POP     DS                      ;;; RESTORE SEGMENT REGISTER
        POP     BP                      ;;; RESTORE FRAME POINTER
        POP     DI                      ;;; RESTORE REGISTER
        POP     DX                      ;;; RESTORE REGISTER
        POP     CX                      ;;; RESTORE REGISTER
        POP     BX                      ;;; RESTORE REGISTER
        POP     AX                      ;;; RESTORE REGISTER
INTRET: IRET                            ;;; RETURN FROM INTERRUPT
SERINT  ENDP

;
; PRTCHR - CHECK FOR CHARACTER AT AUX DEVICE
;
; OUTPUTS:
;       AL      - CHARACTER IF ONE AVAILABLE
;       DX      - NUMBER OF CHARACTERS IN BUFFER
; NOTES:
;       SKIPS RETURN IF NO CHARACTER AVAILABLE.
;
PRTCHR  PROC    NEAR
        CALL    CHKXON                  ; CHECK TO SEE IF XON NEEDED
        CMP     COUNT,0                 ; ANY CHARACTERS IN BUFFER?
        JNZ     PRTCH1                  ; IF NZ YES
        JMP     RSKP                    ; ELSE NO DATA, JUST RETURN
PRTCH1: MOV     SI,SAVESI               ; GET SAVED BUFFER POINTER
        LODSB                           ; GET NEXT BYTE FROM BUFFER
        CMP     SI,OFFSET SOURCE + BUFSIZ ; TIME TO WRAP BUFFER?
        JB      PRTCH2                  ; IF B NO
        MOV     SI,OFFSET SOURCE        ; WRAP BUFFER BACK TO START
PRTCH2: DEC     COUNT                   ; COUNT CHARACTER REMOVED
        MOV     SAVESI,SI               ; SAVE BUFFER POINTER
        MOV     DX,COUNT                ; RETURN NO. OF CHARS IN BUFFER
        RET                             ; AND RETURN
PRTCHR  ENDP

;
; CHKXON - CHECK TO SEE IF AN XON IS NEEDED
;
CHKXON  PROC    NEAR
        PUSH    BX                      ; SAVE REGISTER
        MOV     BX,PORTVAL              ; GET ADDRESS OF PORT STRUCTURE
        CMP     [BX].FLOFLG,FALSE       ; ARE WE DOING FLOW CONTROL?
        JE      CHKXO1                  ; IF E NO, JUST RETURN
        CMP     XOFSNT,FALSE            ; HAVE WE ALREADY SENT AN XOFF?
        JE      CHKXO1                  ; IF E NO, JUST RETURN
        CMP     COUNT,MNTRGH            ; ARE WE BELOW THE TRIGGER?
        JAE     CHKXO1                  ; IF AE NO, JUST RETURN
        MOV     AX,[BX].FLOWC           ; GET XON INTO AH
        CALL    OUTCHR                  ; AND OUTPUT CHARACTER
        NOP                             ; IGNORE ERROR RETURN
        NOP                             ;       "
        NOP                             ;       "
        MOV     XOFSNT,FALSE            ; SAY WE SENT AN XON NOW
CHKXO1: POP     BX                      ; RESTORE REGISTER
        RET                             ; AND RETURN
CHKXON  ENDP

;
; SENDBR - SEND A BREAK OUT THE AUX DEVICE (SERIAL PORT)
;
SENDBR  PROC    NEAR
        PUSH    AX                      ; SAVE REGISTER
        PUSH    CX                      ; SAVE REGISTER
        XOR     CX,CX                   ; CLEAR LOOP VALUE
        MOV     AL,(TxEN+DTR+RxEN+RTS)  ; GET OUTPUT 8251A ENABLE BYTE
        OUT     CMD8251,AL              ; AND ENABLE 8251A
        MOV     AL,(TxEN+DTR+RxEN+SBRK+RTS) ; GET SEND BREAK ENABLE BYTE
        OUT     CMD8251,AL              ; AND SEND BREAK
PAUSE:  LOOP    PAUSE                   ; KILL SOME TIME
        MOV     AL,(TxEN+DTR+RxEN+RTS)  ; GET OUTPUT 8251A ENABLE BYTE
        OUT     CMD8251,AL              ; STOP BREAK
        MOV     AL,(DTR+RxEN+ER+RTS)    ; GET INPUT ENABLE BYTE
        OUT     CMD8251,AL              ; AND RE-ENABLE INPUT
        POP     CX                      ; RESTORE REGISTER
        POP     AX                      ; RESTORE REGISTER
        RET                             ; RETURN
SENDBR  ENDP

;
; POSCUR - POSITION THE CURSOR
;
; INPUTS:
;       DH      - CONTAINS THE ROW
;       DL      - CONTAINS THE COLUMN
;
; NOTES:
;       RETURNS NORMALLY.
;
POSCUR  PROC    NEAR
        MOV     AH,2                    ; SET CODE TO POSITION CURSOR
        MOV     BH,0                    ; SET PAGE NUMBER
        INT     VIDEO                   ; AND POSITION THE CURSOR
        RET                             ; AND RETURN
POSCUR  ENDP

;
; DODEL - DELETE A CHARACTER FROM VIDEO SCREEN
;
; NOTES:
;       RETURNS NORMALLY.
;
DODEL   PROC    NEAR
        MOV     AH,PRSTR                ; SET CODE TO PRINT STRING
        MOV     DX,OFFSET DELSTR        ; SET ERASE STRING
        INT     DOS                     ; AND ERASE CHARACTER
        RET                             ; AND RETURN
DODEL   ENDP

;
; CTLU - CLEAR CURRENT LINE
;
; NOTES:
;       RETURNS NORMALLY.
;
CTLU    PROC    NEAR
        MOV     AH,PRSTR                ; SET CODE TO PRINT STRING
        MOV     DX,OFFSET CLRLIN        ; SET STRING ADDRESS
        INT     DOS                     ; OUTPUT STRING
        CALL    CLEARL                  ; NOW CLEAR THE LINE
        RET                             ; AND RETURN
CTLU    ENDP

;
; COMS - SET THE CURRENT PORT (ONLY ONE ON SANYO)
;
COMS    PROC    NEAR
        MOV     AX,OFFSET PORT1         ; GET ADDRESS OF PORT STRUCTURE
        MOV     PORTVAL,AX              ; AND SET IT
        RET                             ; WE'RE DONE
COMS    ENDP

;
; VTS - WE DON'T DO HEATH EMULATION, SANYO BIOS DOES VT-100 (SOMEWHAT)
;
VTS     PROC    NEAR
        MOV     AH,PRSTR                ; SET CODE TO PRINT STRING
        MOV     DX,OFFSET NOIMP         ; SET ADDRESS OF ERROR MESSAGE
        INT     DOS                     ; AND PRINT IT
        JMP     PRSERR                  ; AND EXIT
VTS     ENDP


VTSTAT  PROC    NEAR    ; For Status display [jrd]
        ret             ; no emulator status to display
VTSTAT  ENDP

;
; LCLINI - DO LOCAL INITIALIZATION
; flags.vtflg holds terminal emulation type (0 = none). [jrd]
LCLINI: MOV     FLAGS.VTFLG,0           ; DON'T KNOW EXACTLY WHAT THIS DOES
        MOV     AX,0EH                  ; SET SCAN CODE FOR ARROW KEY
        MOV     SI,OFFSET RBTRN         ; SET TRANSLATED CODE ADDRESS
        MOV     CX,1                    ; SET SIZE OF TRANSLATION
        CALL    DEFKEY                  ; AND DEFINE THE KEY
        RET                             ; AND RETURN

;
; SHOWKEY - DON'T DO THIS EITHER
;
SHOWKEY:
        MOV     AX,OFFSET SHKMSG        ; SET ADDRESS OF MESSAGE
        MOV     CX,SHKLEN               ; AND LENGTH OF MESSAGE
        RET

;
; BEEP - PRODUCE A BEEP
;
BEEP    PROC    NEAR
        MOV     DL,BELL                 ; SET ADDRESS OF BELL
        MOV     AH,DCONIO               ; SET CODE FOR OUPUT
        INT     DOS                     ; OUTPUT BELL
        RET                             ; AND RETURN
BEEP    ENDP

;
; TERM - TERMINAL EMULATOR (DUMB)
;
; INPUTS:
;       AX - POINTER TO ARGUMENT BLOCK
;
; NOTES:
;       THE SANYO BIOS WILL EMULATE (SOMEWHAT) A VT-100.
;
TERM    PROC    NEAR
        MOV     TELFLG,1                ; SET TERMINAL EMULATION MODE
        MOV     SI,AX                   ; SET ADDRESS OF ARGUMENT BLOCK
        MOV     DI,OFFSET OURARG        ; PLACE TO STORE ARGUMENTS
        MOV     AX,DS                   ; GET DATA SEGMENT ADDRESS
        MOV     ES,AX                   ; AND SET IN EXTRA SEGMENT
        MOV     CX,SIZE TERMARG         ; AND SET SIZE OF MOVE
        REP     MOVSB                   ; COPY ARGUMENT BLOCK TO LOCAL STORE
TERM1:  CALL    PRTCHR                  ; GET NEXT CHAR FROM AUX, ABLE?
        JMP     SHORT TERM2             ; YES, WE HAVE A CHAR
        NOP                             ; SPACE FOR RSKP RETURN
        NOP                             ;       "
        JMP     SHORT TERM3             ; NO CHARACTER, SO CONTINUE
TERM2:  PUSH    AX                      ; SAVE CHARACTER
        MOV     DL,AL                   ; COPY CHARACTER
        MOV     AH,CONOUT               ; SET CODE FOR CONSOLE OUTPUT
        INT     DOS                     ; AND GO PRINT IT
        POP     AX                      ; RESTORE REGISTER
        TEST    OURARG.FLGS,CAPT        ; CAPTURING OUTPUT?
        JZ      TERM3                   ; IF Z NO, CONTINUE
        CALL    OURARG.CAPTR            ; ELSE CALL THE CAPTURE ROUTINE
TERM3:  MOV     AH,DCONIO               ; SET CODE FOR INPUT
        MOV     DL,0FFH                 ; AND CODE
        INT     DOS                     ; CHECK FOR CHARACTER, WELL?
        JZ      TERM1                   ; IF Z NO CHARACTER, GO ON
        CMP     AL,OURARG.ESCC          ; ESCAPE CHARACTER?
        JE      TERM4                   ; YES, EXIT
        PUSH    AX                      ; SAVE CHARACTER
        MOV     AH,AL                   ; COPY THE CHARACTER
        CALL    OUTCHR                  ; OUTPUT CHARACTER TO AUX DEVICE
        NOP                             ; IGNORE ERRORS
        NOP                             ;       "
        NOP                             ;       "
        POP     AX                      ; RESTORE CHARACTER
        TEST    OURARG.FLGS,LCLECHO     ; LOCAL ECHO REQUIRED?
        JZ      TERM1                   ; IF Z NO, CONTINUE
        MOV     DL,AL                   ; ELSE COPY CHARACTER
        MOV     AH,DCONIO               ; SET CODE
        INT     DOS                     ; AND ECHO IT
        JMP     TERM1                   ; AND CONTINUE
TERM4:  MOV     TELFLG,0                ; CLEAR TERMINAL EMULATION MODE
        RET
TERM    ENDP

;
; RSKP - JUMP RETURN WITH SKIPPING
;
RSKP    PROC    NEAR
        POP     BP                      ; GET TOP OF STACK
        ADD     BP,3                    ; ADD SKIP RANGE
        PUSH    BP                      ; AND RESTORE IT
        RET
RSKP    ENDP

CODE    ENDS
        END
