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