OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [ser_a2232fw.ax] - Rev 1275

Go to most recent revision | Compare with Previous | Blame | View Log

;.lib "axm"
;
;begin
;title "A2232 serial board driver"
;
;set modules "2232"
;set executable "2232.bin"
;
;;;;set nolink
;
;set temporary directory "t:"
;
;set assembly options "-m6502 -l60:t:list"
;set link options "bin"; loadadr"
;;;bin2c 2232.bin msc6502.h msc6502code
;end
;
;
; ### Commodore A2232 serial board driver for NetBSD by JM v1.3 ###
;
; - Created 950501 by JM -
;
;
; Serial board driver software.
;
;
% Copyright (c) 1995 Jukka Marin <jmarin@jmp.fi>.
% All rights reserved.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions
% are met:
% 1. Redistributions of source code must retain the above copyright
%    notice, and the entire permission notice in its entirety,
%    including the disclaimer of warranties.
% 2. Redistributions in binary form must reproduce the above copyright
%    notice, this list of conditions and the following disclaimer in the
%    documentation and/or other materials provided with the distribution.
% 3. The name of the author may not be used to endorse or promote
%    products derived from this software without specific prior
%    written permission.
%
% ALTERNATIVELY, this product may be distributed under the terms of
% the GNU General Public License, in which case the provisions of the
% GPL are required INSTEAD OF the above restrictions.  (This clause is
% necessary due to a potential bad interaction between the GPL and
% the restrictions contained in a BSD-style copyright.)
%
% THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED
% WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
% OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
% DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
% INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
% (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
% SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
% HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
% STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
% OF THE POSSIBILITY OF SUCH DAMAGE.
;
;
; Bugs:
;
; - Can't send a break yet
;
;
;
; Edited:
;
; - 950501 by JM -> v0.1        - Created this file.
; - 951029 by JM -> v1.3        - Carrier Detect events now queued in a separate
;                                 queue.
;
;


CODE            equ     $3800           ; start address for program code


CTL_CHAR        equ     $00             ; byte in ibuf is a character
CTL_EVENT       equ     $01             ; byte in ibuf is an event

EVENT_BREAK     equ     $01
EVENT_CDON      equ     $02
EVENT_CDOFF     equ     $03
EVENT_SYNC      equ     $04

XON             equ     $11
XOFF            equ     $13


VARBASE         macro   *starting_address       ; was VARINIT
_varbase        set     \1
                endm

VARDEF          macro   *name space_needs
\1              equ     _varbase
_varbase        set     _varbase+\2
                endm


stz             macro   * address
                 db     $64,\1
                endm

stzax           macro   * address
                 db     $9e,<\1,>\1
                endm


biti            macro   * immediate value
                db      $89,\1
                endm

smb0            macro   * address
                db      $87,\1
                endm
smb1            macro   * address
                db      $97,\1
                endm
smb2            macro   * address
                db      $a7,\1
                endm
smb3            macro   * address
                db      $b7,\1
                endm
smb4            macro   * address
                db      $c7,\1
                endm
smb5            macro   * address
                db      $d7,\1
                endm
smb6            macro   * address
                db      $e7,\1
                endm
smb7            macro   * address
                db      $f7,\1
                endm



;-----------------------------------------------------------------------;
;                                                                       ;
; stuff common for all ports, non-critical (run once / loop)            ;
;                                                                       ;
DO_SLOW         macro   * port_number                                   ;
                .local                  ;                               ;
                lda     CIA+C_PA        ; check all CD inputs           ;
                cmp     CommonCDo       ; changed from previous accptd? ;
                beq     =over           ; nope, do nothing else here    ;
                                        ;                               ;
                cmp     CommonCDb       ; bouncing?                     ;
                beq     =nobounce       ; nope ->                       ;
                                        ;                               ;
                sta     CommonCDb       ; save current state            ;
                lda     #64             ; reinitialize counter          ;
                sta     CommonCDc       ;                               ;
                jmp     =over           ; skip CD save                  ;
                                        ;                               ;
=nobounce       dec     CommonCDc       ; no, decrement bounce counter  ;
                bpl     =over           ; not done yet, so skip CD save ;
                                        ;                               ;
=saveCD         ldx     CDHead          ; get write index               ;
                sta     cdbuf,x         ; save status in buffer         ;
                inx                     ;                               ;
                cpx     CDTail          ; buffer full?                  ;
                .if     ne              ; no: preserve status:          ;
                 stx    CDHead          ; update index in RAM           ;
                 sta    CommonCDo       ; save state for the next check ;
                .end                    ;                               ;
=over           .end    local                                           ;
                endm                                                    ;
                                                                        ;
;-----------------------------------------------------------------------;


; port specific stuff (no data transfer)

DO_PORT         macro   * port_number
                .local                  ;                               ;
                lda     SetUp\1         ; reconfiguration request?      ;
                .if     ne              ; yes:                          ;
                 lda    SoftFlow\1      ; get XON/XOFF flag             ;
                 sta    XonOff\1        ; save it                       ;
                 lda    Param\1         ; get parameter                 ;
                 ora    #%00010000      ; use baud generator for Rx     ;
                 sta    ACIA\1+A_CTRL   ; store in control register     ;
                 stz    OutDisable\1    ; enable transmit output        ;
                 stz    SetUp\1         ; no reconfiguration no more    ;
                .end                    ;                               ;
                                        ;                               ;
                lda     InHead\1        ; get write index               ;
                sbc     InTail\1        ; buffer full soon?             ;
                cmp     #200            ; 200 chars or more in buffer?  ;
                lda     Command\1       ; get Command reg value         ;
                and     #%11110011      ; turn RTS OFF by default       ;
                .if     cc              ; still room in buffer:         ;
                 ora    #%00001000      ; turn RTS ON                   ;
                .end                    ;                               ;
                sta     ACIA\1+A_CMD    ; set/clear RTS                 ;
                                        ;                               ;
                lda     OutFlush\1      ; request to flush output buffer;
                .if     ne              ; yessh!                        ;
                 lda    OutHead\1       ; get head                      ;
                 sta    OutTail\1       ; save as tail                  ;
                 stz    OutDisable\1    ; enable transmit output        ;
                 stz    OutFlush\1      ; clear request                 ;
                .end
                .end    local
                endm


DO_DATA         macro   * port number
                .local
                lda     ACIA\1+A_SR     ; read ACIA status register     ;
                biti    [1<<3]          ; something received?           ;
                .if     ne              ; yes:                          ;
                 biti   [1<<1]          ; framing error?                ;
                 .if    ne              ; yes:                          ;
                  lda   ACIA\1+A_DATA   ; read received character       ;
                  bne   =SEND           ; not break -> ignore it        ;
                  ldx   InHead\1        ; get write pointer             ;
                  lda   #CTL_EVENT      ; get type of byte              ;
                  sta   ictl\1,x        ; save it in InCtl buffer       ;
                  lda   #EVENT_BREAK    ; event code                    ;
                  sta   ibuf\1,x        ; save it as well               ;
                  inx                   ;                               ;
                  cpx   InTail\1        ; still room in buffer?         ;
                  .if   ne              ; absolutely:                   ;
                   stx  InHead\1        ; update index in memory        ;
                  .end                  ;                               ;
                  jmp   =SEND           ; go check if anything to send  ;
                 .end                   ;                               ;
                                        ; normal char received:         ;
                 ldx    InHead\1        ; get write index               ;
                 lda    ACIA\1+A_DATA   ; read received character       ;
                 sta    ibuf\1,x        ; save char in buffer           ;
                 stzax  ictl\1          ; set type to CTL_CHAR          ;
                 inx                    ;                               ;
                 cpx    InTail\1        ; buffer full?                  ;
                 .if    ne              ; no: preserve character:       ;
                  stx   InHead\1        ; update index in RAM           ;
                 .end                   ;                               ;
                 and    #$7f            ; mask off parity if any        ;
                 cmp    #XOFF           ; XOFF from remote host?        ;
                 .if    eq              ; yes:                          ;
                  lda   XonOff\1        ; if XON/XOFF handshaking..     ;
                  sta   OutDisable\1    ; ..disable transmitter         ;
                 .end                   ;                               ;
                .end                    ;                               ;
                                        ;                               ;
                                        ; BUFFER FULL CHECK WAS HERE    ;
                                        ;                               ;
=SEND           lda     ACIA\1+A_SR     ; transmit register empty?      ;
                and     #[1<<4]         ;                               ;
                .if     ne              ; yes:                          ;
                 ldx    OutCtrl\1       ; sending out XON/XOFF?         ;
                 .if    ne              ; yes:                          ;
                  lda   CIA+C_PB        ; check CTS signal              ;
                  and   #[1<<\1]        ; (for this port only)          ;
                  bne   =DONE           ; not allowed to send -> done   ;
                  stx   ACIA\1+A_DATA   ; transmit control char         ;
                  stz   OutCtrl\1       ; clear flag                    ;
                  jmp   =DONE           ; and we're done                ;
                 .end                   ;                               ;
                                        ;                               ;
                 ldx    OutTail\1       ; anything to transmit?         ;
                 cpx    OutHead\1       ;                               ;
                 .if    ne              ; yes:                          ;
                  lda   OutDisable\1    ; allowed to transmit?          ;
                  .if   eq              ; yes:                          ;
                   lda  CIA+C_PB        ; check CTS signal              ;
                   and  #[1<<\1]        ; (for this port only)          ;
                   bne  =DONE           ; not allowed to send -> done   ;
                   lda  obuf\1,x        ; get a char from buffer        ;
                   sta  ACIA\1+A_DATA   ; send it away                  ;
                   inc  OutTail\1       ; update read index             ;
                  .end                  ;                               ;
                 .end                   ;                               ;
                .end                    ;                               ;
=DONE           .end    local
                endm



PORTVAR         macro   * port number
                VARDEF  InHead\1 1
                VARDEF  InTail\1 1
                VARDEF  OutDisable\1 1
                VARDEF  OutHead\1 1
                VARDEF  OutTail\1 1
                VARDEF  OutCtrl\1 1
                VARDEF  OutFlush\1 1
                VARDEF  SetUp\1 1
                VARDEF  Param\1 1
                VARDEF  Command\1 1
                VARDEF  SoftFlow\1 1
                ; private:
                VARDEF  XonOff\1 1
                endm


 VARBASE 0      ; start variables at address $0000
 PORTVAR 0      ; define variables for port 0
 PORTVAR 1      ; define variables for port 1
 PORTVAR 2      ; define variables for port 2
 PORTVAR 3      ; define variables for port 3
 PORTVAR 4      ; define variables for port 4
 PORTVAR 5      ; define variables for port 5
 PORTVAR 6      ; define variables for port 6



 VARDEF Crystal 1       ; 0 = unknown, 1 = normal, 2 = turbo
 VARDEF Pad_a   1
 VARDEF TimerH  1
 VARDEF TimerL  1
 VARDEF CDHead  1
 VARDEF CDTail  1
 VARDEF CDStatus 1
 VARDEF Pad_b   1

 VARDEF CommonCDo 1     ; for carrier detect optimization
 VARDEF CommonCDc 1     ; for carrier detect debouncing
 VARDEF CommonCDb 1     ; for carrier detect debouncing


 VARBASE $0200
 VARDEF obuf0 256       ; output data (characters only)
 VARDEF obuf1 256
 VARDEF obuf2 256
 VARDEF obuf3 256
 VARDEF obuf4 256
 VARDEF obuf5 256
 VARDEF obuf6 256

 VARDEF ibuf0 256       ; input data (characters, events etc - see ictl)
 VARDEF ibuf1 256
 VARDEF ibuf2 256
 VARDEF ibuf3 256
 VARDEF ibuf4 256
 VARDEF ibuf5 256
 VARDEF ibuf6 256

 VARDEF ictl0 256       ; input control information (type of data in ibuf)
 VARDEF ictl1 256
 VARDEF ictl2 256
 VARDEF ictl3 256
 VARDEF ictl4 256
 VARDEF ictl5 256
 VARDEF ictl6 256

 VARDEF cdbuf 256       ; CD event queue


ACIA0           equ     $4400
ACIA1           equ     $4c00
ACIA2           equ     $5400
ACIA3           equ     $5c00
ACIA4           equ     $6400
ACIA5           equ     $6c00
ACIA6           equ     $7400

A_DATA          equ     $00
A_SR            equ     $02
A_CMD           equ     $04
A_CTRL          equ     $06
;  00   write transmit data     read received data
;  02   reset ACIA              read status register
;  04   write command register  read command register
;  06   write control register  read control register

CIA             equ     $7c00           ; 8520 CIA
C_PA            equ     $00             ; port A data register
C_PB            equ     $02             ; port B data register
C_DDRA          equ     $04             ; data direction register for port A
C_DDRB          equ     $06             ; data direction register for port B
C_TAL           equ     $08             ; timer A
C_TAH           equ     $0a
C_TBL           equ     $0c             ; timer B
C_TBH           equ     $0e
C_TODL          equ     $10             ; TOD LSB
C_TODM          equ     $12             ; TOD middle byte
C_TODH          equ     $14             ; TOD MSB
C_DATA          equ     $18             ; serial data register
C_INTCTRL       equ     $1a             ; interrupt control register
C_CTRLA         equ     $1c             ; control register A
C_CTRLB         equ     $1e             ; control register B





                section main,code,CODE-2

                db      >CODE,<CODE

;-----------------------------------------------------------------------;
; here's the initialization code:                                       ;
;                                                                       ;
R_RESET         ldx     #$ff                                            ;
                txs                     ; initialize stack pointer      ;
                cld                     ; in case a 6502 is used...     ;
                ldx     #0              ;                               ;
                lda     #0              ;                               ;
                ldy     #Crystal        ; this many bytes to clear      ;
clr_loop        sta     0,x             ; clear zero page variables     ;
                inx                     ;                               ;
                dey                     ;                               ;
                bne     clr_loop        ;                               ;
                                        ;                               ;
                stz     CommonCDo       ; force CD test at boot         ;
                stz     CommonCDb       ;                               ;
                stz     CDHead          ; clear queue                   ;
                stz     CDTail          ;                               ;
                                        ;                               ;
                lda     #0              ;                               ;
                sta     Pad_a           ;                               ;
                lda     #170            ; test cmp                      ;
                cmp     #100            ;                               ;
                .if     cs              ;                               ;
                 inc    Pad_a           ; C was set                     ;
                .end                    ;                               ;
                                                                        ;
;-----------------------------------------------------------------------;
; Speed check                                                           ;
;-----------------------------------------------------------------------;
                                                                        ;
                lda     Crystal         ; speed already set?            ;
                beq     DoSpeedy        ;                               ;
                jmp     LOOP            ; yes, skip speed test          ;
                                        ;                               ;
DoSpeedy        lda     #%10011000      ; 8N1, 1200/2400 bps            ;
                sta     ACIA0+A_CTRL    ;                               ;
                lda     #%00001011      ; enable DTR                    ;
                sta     ACIA0+A_CMD     ;                               ;
                lda     ACIA0+A_SR      ; read status register          ;
                                        ;                               ;
                lda     #%10000000      ; disable all ints (unnecessary);
                sta     CIA+C_INTCTRL   ;                               ;
                lda     #255            ; program the timer             ;
                sta     CIA+C_TAL       ;                               ;
                sta     CIA+C_TAH       ;                               ;
                                        ;                               ;
                ldx     #0              ;                               ;
                stx     ACIA0+A_DATA    ; transmit a zero               ;
                nop                     ;                               ;
                nop                     ;                               ;
                lda     ACIA0+A_SR      ; read status                   ;
                nop                     ;                               ;
                nop                     ;                               ;
                stx     ACIA0+A_DATA    ; transmit a zero               ;
Speedy1         lda     ACIA0+A_SR      ; read status                   ;
                and     #[1<<4]         ; transmit data reg empty?      ;
                beq     Speedy1         ; not yet, wait more            ;
                                        ;                               ;
                lda     #%00010001      ; load & start the timer        ;
                stx     ACIA0+A_DATA    ; transmit one more zero        ;
                sta     CIA+C_CTRLA     ;                               ;
Speedy2         lda     ACIA0+A_SR      ; read status                   ;
                and     #[1<<4]         ; transmit data reg empty?      ;
                beq     Speedy2         ; not yet, wait more            ;
                stx     CIA+C_CTRLA     ; stop the timer                ;
                                        ;                               ;
                lda     CIA+C_TAL       ; copy timer value for 68k      ;
                sta     TimerL          ;                               ;
                lda     CIA+C_TAH       ;                               ;
                sta     TimerH          ;                               ;
                cmp     #$d0            ; turbo or normal?              ;
                .if     cs              ;                               ;
                 lda    #2              ; turbo! :-)                    ;
                .else                   ;                               ;
                 lda    #1              ; normal :-(                    ;
                .end                    ;                               ;
                sta     Crystal         ;                               ;
                lda     #0              ;                               ;
                sta     ACIA0+A_SR      ;                               ;
                sta     ACIA0+A_CTRL    ; reset UART                    ;
                sta     ACIA0+A_CMD     ;                               ;
                                                                        ;
                jmp     LOOP                                            ;
                                                                        ;
;                                                                       ;
;-----------------------------------------------------------------------;
;                                                                       ;
; The Real Thing:                                                       ;
;                                                                       ;
LOOP            DO_SLOW                 ; do non-critical things        ;
                jsr     do_input        ; check for received data
                DO_PORT 0
                jsr     do_input
                DO_PORT 1
                jsr     do_input
                DO_PORT 2
                jsr     do_input
                DO_PORT 3
                jsr     do_input
                DO_PORT 4
                jsr     do_input
                DO_PORT 5
                jsr     do_input
                DO_PORT 6
                jsr     do_input
                jmp     LOOP


do_input        DO_DATA 0
                DO_DATA 1
                DO_DATA 2
                DO_DATA 3
                DO_DATA 4
                DO_DATA 5
                DO_DATA 6
                rts


;-----------------------------------------------------------------------;
                section vectors,data,$3ffa
                dw      $d0d0
                dw      R_RESET
                dw      $c0ce
;-----------------------------------------------------------------------;



                end



Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.