;>>>>>>>>>>>>>>>>>>>>>>> REMDRIVER.TEXT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;
; For an introduction see the file REMDR.DOC.TEXT
;
;----------------------------------------------------------------------
;
; Serial card driver for Kermit-UCSD  RUG/PT V1.0
;
;----------------------------------------------------------------------
;
; LABEL DEFINITIONS
;
SLOT      .EQU 20          ; various slot 2 labels
SLT2MSB   .EQU 0C2
SLOT2ADR  .EQU 0C200
;
                           ; addresses of the offset bytes to calculate :
FSTATUS   .EQU SLOT2ADR+10 ; entry point for a serial firmware card status
FREAD     .EQU SLOT2ADR+0E ;   "     "    "  "   "       "      "   read
;
DUMMY     .EQU 0FFFF       ; dummy address. will be filled in at cold boot.
;
AP2COMM   .EQU 0C08E+SLOT  ; IBS AP2 serial card (6551 acia) command register.
AP2STREG  .EQU 0C08D+SLOT  ;  "   "    "     "     "    "    status     "
AP2IOREG  .EQU 0C08C+SLOT  ;  "   "    "     "     "    "    I/O        "
;
COMSTREG  .EQU 0C08E+SLOT  ; Apple Com Card (6850 acia) status register.
COMIOREG  .EQU 0C08F+SLOT  ;   "    "    "    "    "    I/O      "
;
HAYSTREG  .EQU 0C086+SLOT  ; Hayes Micromodem (6850 acia) status register.
HAYIOREG  .EQU 0C087+SLOT  ;   "       "        "    "    I/O      "
                           ; (Com Card registers may also work.)
SPEAKER   .EQU 0C030
SPCHAR    .EQU 0BF1C       ; system location for special keyboard character
                           ; checking.
SLT2TYP   .EQU 0BF27+2     ; system location with serial card type
                           ; 0 = no card.
                           ; 1 = not recognized by system.
                           ; 3 = Apple Com card
                           ;     California 7710 ASI1 card
                           ;     Hayes Micromodem card?
                           ; 4 = serial card ( IBS AP2 )
                           ; 6 = Firmware card ( Super Serial Card )
;
NUMSERID  .EQU 02-1        ; number(-1) of serial cards this driver checks.
;
ACJVAFOLD .EQU 0E2         ; pointer to attached copy of BIOS jump vector.
JVAFOLD   .EQU 0EE         ; pointer to BIOS jump vector.
;
CONCK     .EQU DUMMY       ; address of BIOS keyboard check routine.
RINIT     .EQU DUMMY       ; address of BIOS Remote Init routine.
INPORTSTAT.EQU DUMMY       ; address of this driver's Remote status routine.
;
STATREC   .EQU 00          ; temp. zero page pointer to status record.
;
;----------------------------------------------------------------------
;
          .PROC REMDRIVER
;
;----------------------------------------------------------------------
          JMP CONCKHDL     ; The first 3 instructions of CONCK will
                           ; be patched by SYSTEM.ATTACH to point here.
;----------------------------------------------------------------------
;
; Calls to REMREAD, REMSTATUS and REMINIT will be handled here :
;
          TXA              ; X=0 : Remote Read request.
          BEQ REMREAD
          CMP #004         ; X=4 : Remote Status request.
          BEQ REMSTATUS
          CMP #002
          BNE ERROR        ; X=2 : Remote Init request.
          ;----------------
          ;
          ; Remote Init routine :
          ;
          LDX REMRPTR      ; Empty remote input buffer.
          STX REMWPTR      ; ( read-pointer = write-pointer )
          LDX #000         ; zero buffer counter.
          STX BUFCOUNT
PATCH3    JMP ONCERINIT    ; if called for the first time ( cold boot ) then
                           ; do the cold boot init routine. This routine
                           ; patches the JMP instruction to NOP,NOP,NOP so
                           ; later init calls (warm boot) will only empty the
                           ; remin buffer.
          RTS
          ;----------------
ERROR     LDX #003         ; for any other request return error code.
          RTS
;----------------------------------------------------------------------
;
; Remote read routine ( reads only the remin buffer ).
;
REMREAD   JSR CONCKHDL     ; check keyboard and remote input port.
          LDX REMRPTR      ; if remin buffer is empty : keep checking remote
          CPX REMWPTR      ; input port until something arrives.
          BEQ REMREAD
          INX              ; read char from remin buffer, bump read-pointer
          STX REMRPTR      ; decrease buffer count and put char in accu.
          DEC BUFCOUNT
          LDA REMBUF,X
READY     LDX #000         ; no error.
          RTS
;----------------------------------------------------------------------
;
; Remote status routine ( implements UNITSTATUS. see KERM.DOC2.TEXT )
;
REMSTATUS JSR CONCKHDL     ; check keyboard and remote input port.
          PLA              ; save return address.
          STA RETURN
          PLA
          STA RETURN+1
          ;------------
          PLA              ; save address of statusrecord on zero page.
          STA STATREC
          PLA
          STA STATREC+1
          ;------------
          PLA              ; save controlword.
          STA CONTROLW
          PLA
          STA CONTROLW+1
          ;------------
          LDA RETURN+1     ; push return address back on stack.
          PHA
          LDA RETURN
          PHA
          ;----------------------------------
REMINSTAT LDX #000         ; zero registers.
          LDY #000
          ;----------------
          ;
          ; Decipher Controlword.
          ;
          LDA CONTROLW     ; if bit 1 = 0 then the purpose is statusrequest.
          AND #002         ; if bit 1 = 1 then the purpose is controlrequest.
                           ; bit 0 (direction) is not checked.
          BNE REMCNTROL
          LDA CONTROLW+1   ; if bit 13 = 0 then a "normal" request.
          AND #020
          BNE PEEK         ; if bit 13 = 1 then a "special" request.
          ;----------------
          ;
          ; Normal Status Request: load in statusrecord ( 2 bytes ) the number
          ; of characters currently in the remin buffer.
          ;
          LDA BUFCOUNT
LOAD      STA @STATREC,Y
          LDA #00
          INY
          STA @STATREC,Y
          RTS
          ;---------------
          ;
          ; Special Status Request: statusrecord first to bytes contain an
          ; address. Return in statusrecord last 2 bytes the value of the
          ; requested location.
          ;
PEEK      LDA @STATREC,Y
          STA ADR1+1
          INY
          LDA @STATREC,Y
          STA ADR1+2
ADR1      LDA DUMMY        ; DUMMY will be changed to the requested address.
          INY
          BNE LOAD         ; value returned is a Pascal Integer!
          ;----------------
          ;
          ; Control Requests :
          ;
REMCNTROL LDA CONTROLW+1   ; if bit 13 = 0 then a normal controlrequest.
          AND #020
          BNE POKE
          ;----------------
          ; Normal Control Request
          ;
          ; first byte of statusrecord contains
          ; 0..3 : store this byte in SPCHAR.
          ; SPCHAR=0 : CONCK checks class 1 and class 2 special chars.
          ; SPCHAR=1 :   "     "    only        class 2    "     "
          ; SPCHAR=2 :   "     "    only        class 1    "     "
          ; SPCHAR=3 :   "     "           no              "     "
          ; ( see KERM.DOC2.TEXT )
          ;
          ; first byte of statusrecord contains
          ; 4  :  7 bit characters in remin buffer.
          ; 5  :  8 bit      "     "    "    "
          ;
          LDA @STATREC,Y
          CMP #004
          BCS BIT78
          STA SPCHAR
          RTS
          ;-----------------
          ;
          ; Special Control Request : statusrecord first 2 bytes contain a
          ; address. Statusrecord third byte contains the value the location
          ; should contain.
          ;
POKE      LDA @STATREC,Y
          STA ADR2+1
          INY
          LDA @STATREC,Y
          STA ADR2+2
          INY
          LDA @STATREC,Y
ADR2      STA DUMMY        ; DUMMY will be filled in at run time.
          RTS
          ;----------------
BIT78     CMP #005         ; set the flag LOCALPAR for the remin input routine.
          BEQ EIGHTBIT     ; default startup setting is seven bit remin chars.
          LDA #000
          BEQ SETLOCPAR
EIGHTBIT  LDA #080
SETLOCPAR STA LOCALPAR
          RTS
;----------------------------------------------------------------------
;
; Calls to the system CONCK routine come here. A call to this
; driver's remin check routine is inserted so that every time the system
; does any I/O call both the keyboard and the remote input port will be checked.
;
CONCKHDL  PHP           ; repeat first 6 instructions of CONCK.
          PHA
          TXA
          PHA
          TYA
          PHA
          JSR REMINCK   ; check the remote input port.
PATCH2    JMP CONCK     ; enter CONCK at start+6 and return from there to
                        ; system. The 2 bytes after the JMP will be filled
                        ; in at first initialization of this driver.
;----------------------------------------------------------------------
;
; REMINCK  : checks remote input port. If it finds a char, it will put it
;            in the remin buffer.
;
REMINCK   JSR INPORTST  ; checks remote inputport. Carry is set when a char
                        ; is waiting. Returns with char in accu.
                        ; The address INPORTST will be filled in at cold boot
                        ; initialization time to point at the correct status
                        ; routine.
          BCC EMPTY
          BIT LOCALPAR  ; depending on LOCALPAR : strip bit 8 of incomimg char.
          BMI NOCHANGE
          AND #07F
NOCHANGE  LDX REMWPTR   ; bump writepointer.
          INX
          CPX REMRPTR   ; if writepointer = readpointer then buffer is full!
          BNE BUFOK
          ;----------
          PHA           ; in case of buffer overflow :
          TXA           ; give a high pitched bell sound.
          PHA
BELL      LDY #060
BELL1     LDX #020
BELL2     DEX
          BNE BELL2
          LDA SPEAKER
          DEY
          BNE BELL1
          LDA #0FF      ; set buffer count to -1.
          STA BUFCOUNT  ; buffer will thus be emptied.
          PLA
          TAX
          PLA
          ;------------
BUFOK     STX REMWPTR   ; save new writepointer.
          INC BUFCOUNT  ; bump buffer count and
          STA REMBUF,X  ; store received char in buffer.
EMPTY     RTS
;-----------------------------------------------------------------------
;
;   Remote status routines for different serial cards.
;   Only one of these is active after cold boot initialization.
;
;   The status routine returns with the received character (if any) in accu
;   and with the carry set if a character was received.
;
;-----------------------------------------------------------------------
;
;   Status routine for an IBS AP2 serial card with a 6551 acia.
;
AP2STAT   LDA AP2COMM
          ORA #008
          STA AP2COMM
          LDA AP2STREG
          CLC
          AND #028
          EOR #008
          BNE NOTHING1
          SEC
          LDA AP2IOREG
NOTHING1  PHA
          LDA AP2COMM
          AND #0F3
          STA AP2COMM
          PLA
          RTS
;----------------------------------------------------------------------
;
;   Status routine for Hayes Micromodem Card with a 6850 acia.
;   ( Identical to Apple Com Card. Can probably be replaced by Com Card routine
;     if Hayes card is also recognized by the Pascal system as an Apple Com
;     card. )
;
HAYESTAT  LDA HAYSTREG
          LSR A
          BCC NOTHING2
          LDA HAYIOREG
NOTHING2  RTS
;-----------------------------------------------------------------------
;
;   Status routine for an Apple Communications Card or California 7710
;   ASI1 card , both with a 6850 acia.
;
COMSTAT   LDA COMSTREG
          LSR A
          BCC NOTHING3
          LDA COMIOREG
NOTHING3  RTS
;-----------------------------------------------------------------------
;
;   Status routine for a "firmware" card like the Apple Super Serial Card.
;   Firmware cards have there own status and read routines in ROM.
;   The final addresses of the status and read routines will be calculated
;   at cold boot initialization and filled in directly here at PATCH4 and
;   PATCH5.
;
FIRMSTAT  LDX #SLT2MSB   ; do the required initialization.
          LDY #SLOT
          STY 06F8
          STA 0CFFF
          LDA SLOT2ADR
          LDA #001
PATCH4    JSR FSTATUS
          BCC NOTHING
          LDX #SLT2MSB
PATCH5    JSR FREAD      ; returns with char in accu.
          SEC
NOTHING   RTS
;------------------------
;
; If you have extended FINDSER to recognize more serial cards then insert
; here the code for the new serial card's status routine.
;
;----------------------------------------------------------------------------
;
;  Local variables
;
RETURN    .WORD 00
LOCALPAR  .BYTE 00
REMRPTR   .BYTE 00
REMWPTR   .BYTE 00
CONTROLW  .WORD 00
BUFCOUNT  .BYTE 00
;
;
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;
;          START OF THE REMIN BUFFER AREA
;
;          Contains cold boot initialization code.
;
REMBUF   .BYTE 00
;----------------------------------------------------------------------------
;
PBOTABLE .BYTE 01.,02.,04.,05.,07.,08.,28.,29.,43.,44. ; offset bytes to patch
                                                       ; back the BIOS jump
                                                       ; vector.
AP2STPTR .WORD AP2STAT     ; pointers to the various status routines.
COMSTPTR .WORD COMSTAT
HAYESTPTR.WORD HAYESTAT
FIRMSTPTR.WORD FIRMSTAT
;
OFFSET1  .BYTE 04E,01A     ; offset and identification bytes to recognize
OFFSET2  .BYTE 065,02A     ; different serial cards :
IDBYTE1  .BYTE 04D,09C     ; first row = IBS AP2 serial card.
IDBYTE2  .BYTE 0A3,051     ; second row = Hayes Micromodem card.
;
; Insert more offset and Id-bytes for other serial cards here.
; Adjust NUMSERID correspondingly.
;
;-------------------------
ONCERINIT LDX #009         ; cold boot init jumps here.
PATCHBACK LDA PBOTABLE,X   ; get normal BIOS addresses from the attached copy
          TAY              ; and patch back the BIOS jump vector, except
          LDA @ACJVAFOLD,Y ; remote status, read and init.
          STA @JVAFOLD,Y
          DEX
          BPL PATCHBACK
;--------------------------
          CLC              ; get address of CONCK, add 6 to it and patch
          LDY #055.        ; this code.
          LDA @ACJVAFOLD,Y
          ADC #006
          STA PATCH2+1
          INY
          LDA @ACJVAFOLD,Y
          ADC #000
          STA PATCH2+2
;--------------------------
          LDY #031.        ; get address of Remote INIT and patch this code.
          LDA @ACJVAFOLD,Y
          STA PATCH1+1
          INY
          LDA @ACJVAFOLD,Y
          STA PATCH1+2
;--------------------------
          LDA #0EA         ; patch the instruction JMP ONCERINIT to NOP(3x).
          STA PATCH3       ; ONCERINIT will be done only once.
          STA PATCH3+1
          STA PATCH3+2
;--------------------------
;--------------------------
          LDA SLT2TYP      ; find out which serial card there is in slot 2.
          CMP #003
          BNE NXTTYP2
          LDX COMSTPTR     ; Apple Com Card : save pointer to status routine
          LDY COMSTPTR+1   ; in X and Y registers.
          BNE TORINIT
NXTTYP2   CMP #006
          BNE NXTTYP3
          LDA FSTATUS      ; firmware card : get offset bytes from card's ROM
          STA PATCH4+1     ; and patch the status and read routine entry
          LDA FREAD        ; points in the FIRMSTAT routine.
          STA PATCH5+1
          LDX FIRMSTPTR
          LDY FIRMSTPTR+1
          BNE TORINIT
NXTTYP3   CMP #004
          BNE NOTKNOWN
          JSR FINDSER      ; if it is a serial card try to recognize it.
          BMI NOTKNOWN     ; FINDSER returns with minus flag on if card was
          TYA              ; not recognized. Y = ID number of serial card.
          BEQ AP2SER       ; Y=0 : IBS AP2 card.
HAYSER    CMP #001         ; Y=1 : Hayes micromodem card.
                           ; If Hayes card is already recognized as an Apple
                           ; Com card (I don't know), then this part can be
                           ; deleted.
          BNE NOTKNOWN     ; If FINDSER recognizes more serial cards then
                           ; insert here extra code for other cards.
          LDX HAYESTPTR
          LDY HAYESTPTR+1
          BNE TORINIT
AP2SER    LDX AP2STPTR
          LDY AP2STPTR+1
;--------------------------
TORINIT   STX REMINCK+1    ; Patch INPORTSTAT to point to the adress of status
          STY REMINCK+2    ; routine.
PATCH1    JMP RINIT        ; Initialize once the serial card according to the
                           ; card's normal init routine.
NOTKNOWN  LDX #009         ; If card was not recognized then return to system
          LDY #SLOT        ; with error code 9 ( volume not found ).
          RTS
;-------------------------------------------------------------------------
;
;  Serial card recognition routine.
;
;  Checks two unique bytes in the cards ROM space ( C200-C2FF ).
;
FINDSER   LDY #NUMSERID
FNDNEXT1  LDA OFFSET1,Y
          TAX
          LDA SLOT2ADR,X
          CMP IDBYTE1,Y
          BEQ CONFIRM
FNDNEXT2  DEY
          BPL FNDNEXT1
          RTS
CONFIRM   LDA OFFSET2,Y
          TAX
          LDA SLOT2ADR,X
          CMP IDBYTE2,Y
          BNE FNDNEXT2
CODEND    RTS
;---------------------------------------------------------------------------
          .BLOCK 256.+REMBUF-CODEND,00  ; adjusts buffer if init codelength
                                        ; is changed.
;---------------------------------------------------------------------------
          .END
