4
;title "A2232 serial board driver"
7
;set executable "2232.bin"
11
;set temporary directory "t:"
13
;set assembly options "-m6502 -l60:t:list"
14
;set link options "bin"; loadadr"
15
;;;bin2c 2232.bin msc6502.h msc6502code
19
; ### Commodore A2232 serial board driver for NetBSD by JM v1.3 ###
21
; - Created 950501 by JM -
24
; Serial board driver software.
27
% Copyright (c) 1995 Jukka Marin <jmarin@jmp.fi>.
28
% All rights reserved.
30
% Redistribution and use in source and binary forms, with or without
31
% modification, are permitted provided that the following conditions
33
% 1. Redistributions of source code must retain the above copyright
34
% notice, and the entire permission notice in its entirety,
35
% including the disclaimer of warranties.
36
% 2. Redistributions in binary form must reproduce the above copyright
37
% notice, this list of conditions and the following disclaimer in the
38
% documentation and/or other materials provided with the distribution.
39
% 3. The name of the author may not be used to endorse or promote
40
% products derived from this software without specific prior
43
% ALTERNATIVELY, this product may be distributed under the terms of
44
% the GNU General Public License, in which case the provisions of the
45
% GPL are required INSTEAD OF the above restrictions. (This clause is
46
% necessary due to a potential bad interaction between the GPL and
47
% the restrictions contained in a BSD-style copyright.)
49
% THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED
50
% WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
51
% OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
52
% DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
53
% INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
54
% (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
55
% SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56
% HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
57
% STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
58
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
59
% OF THE POSSIBILITY OF SUCH DAMAGE.
64
; - Can't send a break yet
70
; - 950501 by JM -> v0.1 - Created this file.
71
; - 951029 by JM -> v1.3 - Carrier Detect events now queued in a separate
77
CODE equ $3800 ; start address for program code
80
CTL_CHAR equ $00 ; byte in ibuf is a character
81
CTL_EVENT equ $01 ; byte in ibuf is an event
92
VARBASE macro *starting_address ; was VARINIT
96
VARDEF macro *name space_needs
98
_varbase set _varbase+\2
106
stzax macro * address
111
biti macro * immediate value
142
;-----------------------------------------------------------------------;
144
; stuff common for all ports, non-critical (run once / loop) ;
146
DO_SLOW macro * port_number ;
148
lda CIA+C_PA ; check all CD inputs ;
149
cmp CommonCDo ; changed from previous accptd? ;
150
beq =over ; nope, do nothing else here ;
152
cmp CommonCDb ; bouncing? ;
153
beq =nobounce ; nope -> ;
155
sta CommonCDb ; save current state ;
156
lda #64 ; reinitialize counter ;
158
jmp =over ; skip CD save ;
160
=nobounce dec CommonCDc ; no, decrement bounce counter ;
161
bpl =over ; not done yet, so skip CD save ;
163
=saveCD ldx CDHead ; get write index ;
164
sta cdbuf,x ; save status in buffer ;
166
cpx CDTail ; buffer full? ;
167
.if ne ; no: preserve status: ;
168
stx CDHead ; update index in RAM ;
169
sta CommonCDo ; save state for the next check ;
174
;-----------------------------------------------------------------------;
177
; port specific stuff (no data transfer)
179
DO_PORT macro * port_number
181
lda SetUp\1 ; reconfiguration request? ;
183
lda SoftFlow\1 ; get XON/XOFF flag ;
184
sta XonOff\1 ; save it ;
185
lda Param\1 ; get parameter ;
186
ora #%00010000 ; use baud generator for Rx ;
187
sta ACIA\1+A_CTRL ; store in control register ;
188
stz OutDisable\1 ; enable transmit output ;
189
stz SetUp\1 ; no reconfiguration no more ;
192
lda InHead\1 ; get write index ;
193
sbc InTail\1 ; buffer full soon? ;
194
cmp #200 ; 200 chars or more in buffer? ;
195
lda Command\1 ; get Command reg value ;
196
and #%11110011 ; turn RTS OFF by default ;
197
.if cc ; still room in buffer: ;
198
ora #%00001000 ; turn RTS ON ;
200
sta ACIA\1+A_CMD ; set/clear RTS ;
202
lda OutFlush\1 ; request to flush output buffer;
204
lda OutHead\1 ; get head ;
205
sta OutTail\1 ; save as tail ;
206
stz OutDisable\1 ; enable transmit output ;
207
stz OutFlush\1 ; clear request ;
213
DO_DATA macro * port number
215
lda ACIA\1+A_SR ; read ACIA status register ;
216
biti [1<<3] ; something received? ;
218
biti [1<<1] ; framing error? ;
220
lda ACIA\1+A_DATA ; read received character ;
221
bne =SEND ; not break -> ignore it ;
222
ldx InHead\1 ; get write pointer ;
223
lda #CTL_EVENT ; get type of byte ;
224
sta ictl\1,x ; save it in InCtl buffer ;
225
lda #EVENT_BREAK ; event code ;
226
sta ibuf\1,x ; save it as well ;
228
cpx InTail\1 ; still room in buffer? ;
229
.if ne ; absolutely: ;
230
stx InHead\1 ; update index in memory ;
232
jmp =SEND ; go check if anything to send ;
234
; normal char received: ;
235
ldx InHead\1 ; get write index ;
236
lda ACIA\1+A_DATA ; read received character ;
237
sta ibuf\1,x ; save char in buffer ;
238
stzax ictl\1 ; set type to CTL_CHAR ;
240
cpx InTail\1 ; buffer full? ;
241
.if ne ; no: preserve character: ;
242
stx InHead\1 ; update index in RAM ;
244
and #$7f ; mask off parity if any ;
245
cmp #XOFF ; XOFF from remote host? ;
247
lda XonOff\1 ; if XON/XOFF handshaking.. ;
248
sta OutDisable\1 ; ..disable transmitter ;
252
; BUFFER FULL CHECK WAS HERE ;
254
=SEND lda ACIA\1+A_SR ; transmit register empty? ;
257
ldx OutCtrl\1 ; sending out XON/XOFF? ;
259
lda CIA+C_PB ; check CTS signal ;
260
and #[1<<\1] ; (for this port only) ;
261
bne =DONE ; not allowed to send -> done ;
262
stx ACIA\1+A_DATA ; transmit control char ;
263
stz OutCtrl\1 ; clear flag ;
264
jmp =DONE ; and we're done ;
267
ldx OutTail\1 ; anything to transmit? ;
270
lda OutDisable\1 ; allowed to transmit? ;
272
lda CIA+C_PB ; check CTS signal ;
273
and #[1<<\1] ; (for this port only) ;
274
bne =DONE ; not allowed to send -> done ;
275
lda obuf\1,x ; get a char from buffer ;
276
sta ACIA\1+A_DATA ; send it away ;
277
inc OutTail\1 ; update read index ;
286
PORTVAR macro * port number
289
VARDEF OutDisable\1 1
303
VARBASE 0 ; start variables at address $0000
304
PORTVAR 0 ; define variables for port 0
305
PORTVAR 1 ; define variables for port 1
306
PORTVAR 2 ; define variables for port 2
307
PORTVAR 3 ; define variables for port 3
308
PORTVAR 4 ; define variables for port 4
309
PORTVAR 5 ; define variables for port 5
310
PORTVAR 6 ; define variables for port 6
314
VARDEF Crystal 1 ; 0 = unknown, 1 = normal, 2 = turbo
323
VARDEF CommonCDo 1 ; for carrier detect optimization
324
VARDEF CommonCDc 1 ; for carrier detect debouncing
325
VARDEF CommonCDb 1 ; for carrier detect debouncing
329
VARDEF obuf0 256 ; output data (characters only)
337
VARDEF ibuf0 256 ; input data (characters, events etc - see ictl)
345
VARDEF ictl0 256 ; input control information (type of data in ibuf)
353
VARDEF cdbuf 256 ; CD event queue
368
; 00 write transmit data read received data
369
; 02 reset ACIA read status register
370
; 04 write command register read command register
371
; 06 write control register read control register
373
CIA equ $7c00 ; 8520 CIA
374
C_PA equ $00 ; port A data register
375
C_PB equ $02 ; port B data register
376
C_DDRA equ $04 ; data direction register for port A
377
C_DDRB equ $06 ; data direction register for port B
378
C_TAL equ $08 ; timer A
380
C_TBL equ $0c ; timer B
382
C_TODL equ $10 ; TOD LSB
383
C_TODM equ $12 ; TOD middle byte
384
C_TODH equ $14 ; TOD MSB
385
C_DATA equ $18 ; serial data register
386
C_INTCTRL equ $1a ; interrupt control register
387
C_CTRLA equ $1c ; control register A
388
C_CTRLB equ $1e ; control register B
394
section main,code,CODE-2
398
;-----------------------------------------------------------------------;
399
; here's the initialization code: ;
402
txs ; initialize stack pointer ;
403
cld ; in case a 6502 is used... ;
406
ldy #Crystal ; this many bytes to clear ;
407
clr_loop sta 0,x ; clear zero page variables ;
412
stz CommonCDo ; force CD test at boot ;
414
stz CDHead ; clear queue ;
419
lda #170 ; test cmp ;
422
inc Pad_a ; C was set ;
425
;-----------------------------------------------------------------------;
427
;-----------------------------------------------------------------------;
429
lda Crystal ; speed already set? ;
431
jmp LOOP ; yes, skip speed test ;
433
DoSpeedy lda #%10011000 ; 8N1, 1200/2400 bps ;
435
lda #%00001011 ; enable DTR ;
437
lda ACIA0+A_SR ; read status register ;
439
lda #%10000000 ; disable all ints (unnecessary);
440
sta CIA+C_INTCTRL ; ;
441
lda #255 ; program the timer ;
446
stx ACIA0+A_DATA ; transmit a zero ;
449
lda ACIA0+A_SR ; read status ;
452
stx ACIA0+A_DATA ; transmit a zero ;
453
Speedy1 lda ACIA0+A_SR ; read status ;
454
and #[1<<4] ; transmit data reg empty? ;
455
beq Speedy1 ; not yet, wait more ;
457
lda #%00010001 ; load & start the timer ;
458
stx ACIA0+A_DATA ; transmit one more zero ;
460
Speedy2 lda ACIA0+A_SR ; read status ;
461
and #[1<<4] ; transmit data reg empty? ;
462
beq Speedy2 ; not yet, wait more ;
463
stx CIA+C_CTRLA ; stop the timer ;
465
lda CIA+C_TAL ; copy timer value for 68k ;
469
cmp #$d0 ; turbo or normal? ;
471
lda #2 ; turbo! :-) ;
473
lda #1 ; normal :-( ;
478
sta ACIA0+A_CTRL ; reset UART ;
484
;-----------------------------------------------------------------------;
488
LOOP DO_SLOW ; do non-critical things ;
489
jsr do_input ; check for received data
517
;-----------------------------------------------------------------------;
518
section vectors,data,$3ffa
522
;-----------------------------------------------------------------------;