123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529 |
- ;.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
|