]> git.sur5r.net Git - cc65/blobdiff - libsrc/atmos/ser/atmos-acia.s
use first free IOCB for "GRAPHICS 0" call instead of using a hard-coded one
[cc65] / libsrc / atmos / ser / atmos-acia.s
index c2b48c9fc9c6b75c31433e1f9b75d750dc97626c..9d742bf66e324fda0d749acd3734dcc549b2cf5d 100644 (file)
 ; interrupt handling assumes that the 65816 is in 6502-emulation mode.
 ;
 
-       .include        "zeropage.inc"
-       .include        "ser-kernel.inc"
-       .include        "ser-error.inc"
+        .include        "zeropage.inc"
+        .include        "ser-kernel.inc"
+        .include        "ser-error.inc"
 
 ; ------------------------------------------------------------------------
 ; Header. Includes jump table
 
-       .segment        "JUMPTABLE"
+        .segment        "JUMPTABLE"
 
-       ; Driver signature
-       .byte   $73, $65, $72           ; "ser"
-       .byte   SER_API_VERSION         ; Serial API version number
+        ; Driver signature
+        .byte   $73, $65, $72           ; "ser"
+        .byte   SER_API_VERSION         ; Serial API version number
 
-       ; Jump table.
-       .addr   INSTALL
-       .addr   UNINSTALL
-       .addr   OPEN
-       .addr   CLOSE
-       .addr   GET
-       .addr   PUT
-       .addr   STATUS
-       .addr   IOCTL
-       .addr   IRQ
+        ; Library reference
+        .addr   $0000
+
+        ; Jump table
+        .addr   INSTALL
+        .addr   UNINSTALL
+        .addr   OPEN
+        .addr   CLOSE
+        .addr   GET
+        .addr   PUT
+        .addr   STATUS
+        .addr   IOCTL
+        .addr   IRQ
 
 ;----------------------------------------------------------------------------
 ; I/O definitions
 
-ACIA           = $031C
-ACIA_DATA      = ACIA+0        ; Data register
-ACIA_STATUS    = ACIA+1        ; Status register
-ACIA_CMD       = ACIA+2        ; Command register
-ACIA_CTRL      = ACIA+3        ; Control register
+ACIA            = $031C
+ACIA_DATA       = ACIA+0        ; Data register
+ACIA_STATUS     = ACIA+1        ; Status register
+ACIA_CMD        = ACIA+2        ; Command register
+ACIA_CTRL       = ACIA+3        ; Control register
 
 ;----------------------------------------------------------------------------
 ; Global variables
 
-       .bss
-
-RecvHead:      .res    1       ; Head of receive buffer
-RecvTail:      .res    1       ; Tail of receive buffer
-RecvFreeCnt:   .res    1       ; Number of bytes in receive buffer
-SendHead:      .res    1       ; Head of send buffer
-SendTail:      .res    1       ; Tail of send buffer
-SendFreeCnt:   .res    1       ; Number of bytes in send buffer
-
-Stopped:       .res    1       ; Flow-stopped flag
-RtsOff:                .res    1       ;
-
-RecvBuf:       .res    256     ; Receive buffers: 256 bytes
-SendBuf:       .res    256     ; Send buffers: 256 bytes
-
-Index:         .res    1       ; I/O register index
-
-       .rodata
-
-       ; Tables used to translate RS232 params into register values
-BaudTable:                     ; bit7 = 1 means setting is invalid
-       .byte   $FF             ; SER_BAUD_45_5
-       .byte   $01             ; SER_BAUD_50
-       .byte   $02             ; SER_BAUD_75
-       .byte   $03             ; SER_BAUD_110
-       .byte   $04             ; SER_BAUD_134_5
-       .byte   $05             ; SER_BAUD_150
-       .byte   $06             ; SER_BAUD_300
-       .byte   $07             ; SER_BAUD_600
-       .byte   $08             ; SER_BAUD_1200
-       .byte   $09             ; SER_BAUD_1800
-       .byte   $0A             ; SER_BAUD_2400
-       .byte   $0B             ; SER_BAUD_3600
-       .byte   $0C             ; SER_BAUD_4800
-       .byte   $0D             ; SER_BAUD_7200
-       .byte   $0E             ; SER_BAUD_9600
-       .byte   $0F             ; SER_BAUD_19200
-       .byte   $FF             ; SER_BAUD_38400
-       .byte   $FF             ; SER_BAUD_57600
-       .byte   $FF             ; SER_BAUD_115200
-       .byte   $FF             ; SER_BAUD_230400
+        .bss
+
+RecvHead:       .res    1       ; Head of receive buffer
+RecvTail:       .res    1       ; Tail of receive buffer
+RecvFreeCnt:    .res    1       ; Number of bytes in receive buffer
+SendHead:       .res    1       ; Head of send buffer
+SendTail:       .res    1       ; Tail of send buffer
+SendFreeCnt:    .res    1       ; Number of bytes in send buffer
+
+Stopped:        .res    1       ; Flow-stopped flag
+RtsOff:         .res    1       ;
+
+RecvBuf:        .res    256     ; Receive buffers: 256 bytes
+SendBuf:        .res    256     ; Send buffers: 256 bytes
+
+Index:          .res    1       ; I/O register index
+
+        .rodata
+
+        ; Tables used to translate RS232 params into register values
+BaudTable:                      ; bit7 = 1 means setting is invalid
+        .byte   $FF             ; SER_BAUD_45_5
+        .byte   $01             ; SER_BAUD_50
+        .byte   $02             ; SER_BAUD_75
+        .byte   $03             ; SER_BAUD_110
+        .byte   $04             ; SER_BAUD_134_5
+        .byte   $05             ; SER_BAUD_150
+        .byte   $06             ; SER_BAUD_300
+        .byte   $07             ; SER_BAUD_600
+        .byte   $08             ; SER_BAUD_1200
+        .byte   $09             ; SER_BAUD_1800
+        .byte   $0A             ; SER_BAUD_2400
+        .byte   $0B             ; SER_BAUD_3600
+        .byte   $0C             ; SER_BAUD_4800
+        .byte   $0D             ; SER_BAUD_7200
+        .byte   $0E             ; SER_BAUD_9600
+        .byte   $0F             ; SER_BAUD_19200
+        .byte   $FF             ; SER_BAUD_38400
+        .byte   $FF             ; SER_BAUD_57600
+        .byte   $FF             ; SER_BAUD_115200
+        .byte   $FF             ; SER_BAUD_230400
 BitTable:
-       .byte   $60             ; SER_BITS_5
-       .byte   $40             ; SER_BITS_6
-       .byte   $20             ; SER_BITS_7
-       .byte   $00             ; SER_BITS_8
+        .byte   $60             ; SER_BITS_5
+        .byte   $40             ; SER_BITS_6
+        .byte   $20             ; SER_BITS_7
+        .byte   $00             ; SER_BITS_8
 StopTable:
-       .byte   $00             ; SER_STOP_1
-       .byte   $80             ; SER_STOP_2
+        .byte   $00             ; SER_STOP_1
+        .byte   $80             ; SER_STOP_2
 ParityTable:
-       .byte   $00             ; SER_PAR_NONE
-       .byte   $20             ; SER_PAR_ODD
-       .byte   $60             ; SER_PAR_EVEN
-       .byte   $A0             ; SER_PAR_MARK
-       .byte   $E0             ; SER_PAR_SPACE
+        .byte   $00             ; SER_PAR_NONE
+        .byte   $20             ; SER_PAR_ODD
+        .byte   $60             ; SER_PAR_EVEN
+        .byte   $A0             ; SER_PAR_MARK
+        .byte   $E0             ; SER_PAR_SPACE
 
-       .code
+        .code
 
 ;----------------------------------------------------------------------------
 ; INSTALL: Is called after the driver is loaded into memory. If possible,
@@ -134,91 +137,91 @@ ParityTable:
 INSTALL:
 UNINSTALL:
 CLOSE:
-       ldx     Index           ; Check for open port
-       beq     :+
+        ldx     Index           ; Check for open port
+        beq     :+
 
-       ; Deactivate DTR and disable 6551 interrupts
-       lda     #%00001010
-       sta     ACIA_CMD,x
+        ; Deactivate DTR and disable 6551 interrupts
+        lda     #%00001010
+        sta     ACIA_CMD,x
 
-       ; Done, return an error code
-:      lda     #<SER_ERR_OK
-       tax                     ; A is zero
-       stx     Index           ; Mark port as closed
-       rts
+        ; Done, return an error code
+:       lda     #<SER_ERR_OK
+        tax                     ; A is zero
+        stx     Index           ; Mark port as closed
+        rts
 
 ;----------------------------------------------------------------------------
 ; OPEN: A pointer to a ser_params structure is passed in ptr1.
 ; Must return an SER_ERR_xx code in a/x.
 
 OPEN:
-       ; Check if the handshake setting is valid
-       ldy     #SER_PARAMS::HANDSHAKE  ; Handshake
-       lda     (ptr1),y
-       cmp     #SER_HS_HW              ; This is all we support
-       bne     InvParam
-
-       ; Initialize buffers
-       ldy     #$00
-       sty     Stopped
-       sty     RecvHead
-       sty     RecvTail
-       sty     SendHead
-       sty     SendTail
-       dey                             ; Y = 255
-       sty     RecvFreeCnt
-       sty     SendFreeCnt
-
-       ; Set the value for the control register, which contains stop bits,
-       ; word length and the baud rate.
-       ldy     #SER_PARAMS::BAUDRATE
-       lda     (ptr1),y                ; Baudrate index
-       tay
-       lda     BaudTable,y             ; Get 6551 value
-       bmi     InvBaud                 ; Branch if rate not supported
-       sta     tmp1
-
-       ldy     #SER_PARAMS::DATABITS   ; Databits
-       lda     (ptr1),y
-       tay
-       lda     BitTable,y
-       ora     tmp1
-       sta     tmp1
-
-       ldy     #SER_PARAMS::STOPBITS   ; Stopbits
-       lda     (ptr1),y
-       tay
-       lda     StopTable,y
-       ora     tmp1
-       ora     #%00010000              ; Receiver clock source = baudrate
-       sta     ACIA_CTRL
-
-       ; Set the value for the command register. We remember the base value
-       ; in RtsOff, since we will have to manipulate ACIA_CMD often.
-       ldy     #SER_PARAMS::PARITY     ; Parity
-       lda     (ptr1),y
-       tay
-       lda     ParityTable,y
-       ora     #%00000001              ; DTR active
-       sta     RtsOff
-       ora     #%00001000              ; Enable receive interrupts
-       sta     ACIA_CMD
-
-       ; Done
-       stx     Index                   ; Mark port as open
-       lda     #<SER_ERR_OK
-       tax                             ; A is zero
-       rts
-
-       ; Invalid parameter
-InvParam:lda   #<SER_ERR_INIT_FAILED
-       ldx     #>SER_ERR_INIT_FAILED
-       rts
-
-       ; Baud rate not available
-InvBaud:lda    #<SER_ERR_BAUD_UNAVAIL
-       ldx     #>SER_ERR_BAUD_UNAVAIL
-       rts
+        ; Check if the handshake setting is valid
+        ldy     #SER_PARAMS::HANDSHAKE  ; Handshake
+        lda     (ptr1),y
+        cmp     #SER_HS_HW              ; This is all we support
+        bne     InvParam
+
+        ; Initialize buffers
+        ldy     #$00
+        sty     Stopped
+        sty     RecvHead
+        sty     RecvTail
+        sty     SendHead
+        sty     SendTail
+        dey                             ; Y = 255
+        sty     RecvFreeCnt
+        sty     SendFreeCnt
+
+        ; Set the value for the control register, which contains stop bits,
+        ; word length and the baud rate.
+        ldy     #SER_PARAMS::BAUDRATE
+        lda     (ptr1),y                ; Baudrate index
+        tay
+        lda     BaudTable,y             ; Get 6551 value
+        bmi     InvBaud                 ; Branch if rate not supported
+        sta     tmp1
+
+        ldy     #SER_PARAMS::DATABITS   ; Databits
+        lda     (ptr1),y
+        tay
+        lda     BitTable,y
+        ora     tmp1
+        sta     tmp1
+
+        ldy     #SER_PARAMS::STOPBITS   ; Stopbits
+        lda     (ptr1),y
+        tay
+        lda     StopTable,y
+        ora     tmp1
+        ora     #%00010000              ; Receiver clock source = baudrate
+        sta     ACIA_CTRL
+
+        ; Set the value for the command register. We remember the base value
+        ; in RtsOff, since we will have to manipulate ACIA_CMD often.
+        ldy     #SER_PARAMS::PARITY     ; Parity
+        lda     (ptr1),y
+        tay
+        lda     ParityTable,y
+        ora     #%00000001              ; DTR active
+        sta     RtsOff
+        ora     #%00001000              ; Enable receive interrupts
+        sta     ACIA_CMD
+
+        ; Done
+        stx     Index                   ; Mark port as open
+        lda     #<SER_ERR_OK
+        tax                             ; A is zero
+        rts
+
+        ; Invalid parameter
+InvParam:lda    #<SER_ERR_INIT_FAILED
+        ldx     #>SER_ERR_INIT_FAILED
+        rts
+
+        ; Baud rate not available
+InvBaud:lda     #<SER_ERR_BAUD_UNAVAIL
+        ldx     #>SER_ERR_BAUD_UNAVAIL
+        rts
 
 ;----------------------------------------------------------------------------
 ; GET: Will fetch a character from the receive buffer and store it into the
@@ -226,82 +229,82 @@ InvBaud:lda       #<SER_ERR_BAUD_UNAVAIL
 ; returned.
 
 GET:
-       ldy     SendFreeCnt     ; Send data if necessary
-       iny                     ; Y == $FF?
-       beq     :+
-       lda     #$00            ; TryHard = false
-       jsr     TryToSend
-
-       ; Check for buffer empty
-:      lda     RecvFreeCnt     ; (25)
-       cmp     #$FF
-       bne     :+
-       lda     #<SER_ERR_NO_DATA
-       ldx     #>SER_ERR_NO_DATA
-       rts
-
-       ; Check for flow stopped & enough free: release flow control
-:      ldy     Stopped         ; (34)
-       beq     :+
-       cmp     #63
-       bcc     :+
-       lda     #$00
-       sta     Stopped
-       lda     RtsOff
-       ora     #%00001000
-       sta     ACIA_CMD
-
-       ; Get byte from buffer
-:      ldy     RecvHead        ; (41)
-       lda     RecvBuf,y
-       inc     RecvHead
-       inc     RecvFreeCnt
-       ldx     #$00            ; (59)
-       sta     (ptr1,x)
-       txa                     ; Return code = 0
-       rts
+        ldy     SendFreeCnt     ; Send data if necessary
+        iny                     ; Y == $FF?
+        beq     :+
+        lda     #$00            ; TryHard = false
+        jsr     TryToSend
+
+        ; Check for buffer empty
+:       lda     RecvFreeCnt     ; (25)
+        cmp     #$FF
+        bne     :+
+        lda     #<SER_ERR_NO_DATA
+        ldx     #>SER_ERR_NO_DATA
+        rts
+
+        ; Check for flow stopped & enough free: release flow control
+:       ldy     Stopped         ; (34)
+        beq     :+
+        cmp     #63
+        bcc     :+
+        lda     #$00
+        sta     Stopped
+        lda     RtsOff
+        ora     #%00001000
+        sta     ACIA_CMD
+
+        ; Get byte from buffer
+:       ldy     RecvHead        ; (41)
+        lda     RecvBuf,y
+        inc     RecvHead
+        inc     RecvFreeCnt
+        ldx     #$00            ; (59)
+        sta     (ptr1,x)
+        txa                     ; Return code = 0
+        rts
 
 ;----------------------------------------------------------------------------
 ; PUT: Output character in A.
 ; Must return an SER_ERR_xx code in a/x.
 
 PUT:
-       ; Try to send
-       ldy     SendFreeCnt
-       iny                     ; Y = $FF?
-       beq     :+
-       pha
-       lda     #$00            ; TryHard = false
-       jsr     TryToSend
-       pla
-
-       ; Put byte into send buffer & send
-:      ldy     SendFreeCnt
-       bne     :+
-       lda     #<SER_ERR_OVERFLOW
-       ldx     #>SER_ERR_OVERFLOW
-       rts
-
-:      ldy     SendTail
-       sta     SendBuf,y
-       inc     SendTail
-       dec     SendFreeCnt
-       lda     #$FF            ; TryHard = true
-       jsr     TryToSend
-       lda     #<SER_ERR_OK
-       tax
-       rts
+        ; Try to send
+        ldy     SendFreeCnt
+        iny                     ; Y = $FF?
+        beq     :+
+        pha
+        lda     #$00            ; TryHard = false
+        jsr     TryToSend
+        pla
+
+        ; Put byte into send buffer & send
+:       ldy     SendFreeCnt
+        bne     :+
+        lda     #<SER_ERR_OVERFLOW
+        ldx     #>SER_ERR_OVERFLOW
+        rts
+
+:       ldy     SendTail
+        sta     SendBuf,y
+        inc     SendTail
+        dec     SendFreeCnt
+        lda     #$FF            ; TryHard = true
+        jsr     TryToSend
+        lda     #<SER_ERR_OK
+        tax
+        rts
 
 ;----------------------------------------------------------------------------
 ; STATUS: Return the status in the variable pointed to by ptr1.
 ; Must return an SER_ERR_xx code in a/x.
 
 STATUS:
-       lda     ACIA_STATUS
-       ldx     #$00
-       sta     (ptr1,x)
-       txa                     ; SER_ERR_OK
-       rts
+        lda     ACIA_STATUS
+        ldx     #$00
+        sta     (ptr1,x)
+        txa                     ; SER_ERR_OK
+        rts
 
 ;----------------------------------------------------------------------------
 ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
@@ -309,9 +312,9 @@ STATUS:
 ; Must return an SER_ERR_xx code in a/x.
 
 IOCTL:
-       lda     #<SER_ERR_INV_IOCTL
-       ldx     #>SER_ERR_INV_IOCTL
-       rts
+        lda     #<SER_ERR_INV_IOCTL
+        ldx     #>SER_ERR_INV_IOCTL
+        rts
 
 ;----------------------------------------------------------------------------
 ; IRQ: Called from the builtin runtime IRQ handler as a subroutine. All
@@ -320,55 +323,55 @@ IOCTL:
 ; was handled, otherwise with carry clear.
 
 IRQ:
-       ldx     Index           ; Check for open port
-       beq     Done
-       lda     ACIA_STATUS,x   ; Check ACIA status for receive interrupt
-       and     #$08
-       beq     Done            ; Jump if no ACIA interrupt
-       lda     ACIA_DATA,x     ; Get byte from ACIA
-       ldy     RecvFreeCnt     ; Check if we have free space left
-       beq     Flow            ; Jump if no space in receive buffer
-       ldy     RecvTail        ; Load buffer pointer
-       sta     RecvBuf,y       ; Store received byte in buffer
-       inc     RecvTail        ; Increment buffer pointer
-       dec     RecvFreeCnt     ; Decrement free space counter
-       ldy     RecvFreeCnt     ; Check for buffer space low
-       cpy     #33
-       bcc     Flow            ; Assert flow control if buffer space low
-       rts                     ; Interrupt handled (carry already set)
-
-       ; Assert flow control if buffer space too low
-Flow:  lda     RtsOff
-       sta     ACIA_CMD,x
-       sta     Stopped
-       sec                     ; Interrupt handled
-Done:  rts
+        ldx     Index           ; Check for open port
+        beq     Done
+        lda     ACIA_STATUS,x   ; Check ACIA status for receive interrupt
+        and     #$08
+        beq     Done            ; Jump if no ACIA interrupt
+        lda     ACIA_DATA,x     ; Get byte from ACIA
+        ldy     RecvFreeCnt     ; Check if we have free space left
+        beq     Flow            ; Jump if no space in receive buffer
+        ldy     RecvTail        ; Load buffer pointer
+        sta     RecvBuf,y       ; Store received byte in buffer
+        inc     RecvTail        ; Increment buffer pointer
+        dec     RecvFreeCnt     ; Decrement free space counter
+        ldy     RecvFreeCnt     ; Check for buffer space low
+        cpy     #33
+        bcc     Flow            ; Assert flow control if buffer space low
+        rts                     ; Interrupt handled (carry already set)
+
+        ; Assert flow control if buffer space too low
+Flow:   lda     RtsOff
+        sta     ACIA_CMD,x
+        sta     Stopped
+        sec                     ; Interrupt handled
+Done:   rts
 
 ;----------------------------------------------------------------------------
 ; Try to send a byte. Internal routine. A = TryHard
 
 TryToSend:
-       sta     tmp1            ; Remember tryHard flag
-Again: lda     SendFreeCnt
-       cmp     #$FF
-       beq     Quit            ; Bail out
-
-       ; Check for flow stopped
-       lda     Stopped
-       bne     Quit            ; Bail out
-
-       ; Check that ACIA is ready to send
-       lda     ACIA_STATUS
-       and     #$10
-       bne     Send
-       bit     tmp1            ; Keep trying if must try hard
-       bmi     Again
-Quit:  rts
-
-       ; Send byte and try again
-Send:  ldy     SendHead
-       lda     SendBuf,y
-       sta     ACIA_DATA
-       inc     SendHead
-       inc     SendFreeCnt
-       jmp     Again
+        sta     tmp1            ; Remember tryHard flag
+Again:  lda     SendFreeCnt
+        cmp     #$FF
+        beq     Quit            ; Bail out
+
+        ; Check for flow stopped
+        lda     Stopped
+        bne     Quit            ; Bail out
+
+        ; Check that ACIA is ready to send
+        lda     ACIA_STATUS
+        and     #$10
+        bne     Send
+        bit     tmp1            ; Keep trying if must try hard
+        bmi     Again
+Quit:   rts
+
+        ; Send byte and try again
+Send:   ldy     SendHead
+        lda     SendBuf,y
+        sta     ACIA_DATA
+        inc     SendHead
+        inc     SendFreeCnt
+        jmp     Again