diff options
Diffstat (limited to 'drivers/char/ser_a2232fw.ax')
-rw-r--r-- | drivers/char/ser_a2232fw.ax | 529 |
1 files changed, 529 insertions, 0 deletions
diff --git a/drivers/char/ser_a2232fw.ax b/drivers/char/ser_a2232fw.ax new file mode 100644 index 000000000000..736438032768 --- /dev/null +++ b/drivers/char/ser_a2232fw.ax | |||
@@ -0,0 +1,529 @@ | |||
1 | ;.lib "axm" | ||
2 | ; | ||
3 | ;begin | ||
4 | ;title "A2232 serial board driver" | ||
5 | ; | ||
6 | ;set modules "2232" | ||
7 | ;set executable "2232.bin" | ||
8 | ; | ||
9 | ;;;;set nolink | ||
10 | ; | ||
11 | ;set temporary directory "t:" | ||
12 | ; | ||
13 | ;set assembly options "-m6502 -l60:t:list" | ||
14 | ;set link options "bin"; loadadr" | ||
15 | ;;;bin2c 2232.bin msc6502.h msc6502code | ||
16 | ;end | ||
17 | ; | ||
18 | ; | ||
19 | ; ### Commodore A2232 serial board driver for NetBSD by JM v1.3 ### | ||
20 | ; | ||
21 | ; - Created 950501 by JM - | ||
22 | ; | ||
23 | ; | ||
24 | ; Serial board driver software. | ||
25 | ; | ||
26 | ; | ||
27 | % Copyright (c) 1995 Jukka Marin <jmarin@jmp.fi>. | ||
28 | % All rights reserved. | ||
29 | % | ||
30 | % Redistribution and use in source and binary forms, with or without | ||
31 | % modification, are permitted provided that the following conditions | ||
32 | % are met: | ||
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 | ||
41 | % written permission. | ||
42 | % | ||
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.) | ||
48 | % | ||
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. | ||
60 | ; | ||
61 | ; | ||
62 | ; Bugs: | ||
63 | ; | ||
64 | ; - Can't send a break yet | ||
65 | ; | ||
66 | ; | ||
67 | ; | ||
68 | ; Edited: | ||
69 | ; | ||
70 | ; - 950501 by JM -> v0.1 - Created this file. | ||
71 | ; - 951029 by JM -> v1.3 - Carrier Detect events now queued in a separate | ||
72 | ; queue. | ||
73 | ; | ||
74 | ; | ||
75 | |||
76 | |||
77 | CODE equ $3800 ; start address for program code | ||
78 | |||
79 | |||
80 | CTL_CHAR equ $00 ; byte in ibuf is a character | ||
81 | CTL_EVENT equ $01 ; byte in ibuf is an event | ||
82 | |||
83 | EVENT_BREAK equ $01 | ||
84 | EVENT_CDON equ $02 | ||
85 | EVENT_CDOFF equ $03 | ||
86 | EVENT_SYNC equ $04 | ||
87 | |||
88 | XON equ $11 | ||
89 | XOFF equ $13 | ||
90 | |||
91 | |||
92 | VARBASE macro *starting_address ; was VARINIT | ||
93 | _varbase set \1 | ||
94 | endm | ||
95 | |||
96 | VARDEF macro *name space_needs | ||
97 | \1 equ _varbase | ||
98 | _varbase set _varbase+\2 | ||
99 | endm | ||
100 | |||
101 | |||
102 | stz macro * address | ||
103 | db $64,\1 | ||
104 | endm | ||
105 | |||
106 | stzax macro * address | ||
107 | db $9e,<\1,>\1 | ||
108 | endm | ||
109 | |||
110 | |||
111 | biti macro * immediate value | ||
112 | db $89,\1 | ||
113 | endm | ||
114 | |||
115 | smb0 macro * address | ||
116 | db $87,\1 | ||
117 | endm | ||
118 | smb1 macro * address | ||
119 | db $97,\1 | ||
120 | endm | ||
121 | smb2 macro * address | ||
122 | db $a7,\1 | ||
123 | endm | ||
124 | smb3 macro * address | ||
125 | db $b7,\1 | ||
126 | endm | ||
127 | smb4 macro * address | ||
128 | db $c7,\1 | ||
129 | endm | ||
130 | smb5 macro * address | ||
131 | db $d7,\1 | ||
132 | endm | ||
133 | smb6 macro * address | ||
134 | db $e7,\1 | ||
135 | endm | ||
136 | smb7 macro * address | ||
137 | db $f7,\1 | ||
138 | endm | ||
139 | |||
140 | |||
141 | |||
142 | ;-----------------------------------------------------------------------; | ||
143 | ; ; | ||
144 | ; stuff common for all ports, non-critical (run once / loop) ; | ||
145 | ; ; | ||
146 | DO_SLOW macro * port_number ; | ||
147 | .local ; ; | ||
148 | lda CIA+C_PA ; check all CD inputs ; | ||
149 | cmp CommonCDo ; changed from previous accptd? ; | ||
150 | beq =over ; nope, do nothing else here ; | ||
151 | ; ; | ||
152 | cmp CommonCDb ; bouncing? ; | ||
153 | beq =nobounce ; nope -> ; | ||
154 | ; ; | ||
155 | sta CommonCDb ; save current state ; | ||
156 | lda #64 ; reinitialize counter ; | ||
157 | sta CommonCDc ; ; | ||
158 | jmp =over ; skip CD save ; | ||
159 | ; ; | ||
160 | =nobounce dec CommonCDc ; no, decrement bounce counter ; | ||
161 | bpl =over ; not done yet, so skip CD save ; | ||
162 | ; ; | ||
163 | =saveCD ldx CDHead ; get write index ; | ||
164 | sta cdbuf,x ; save status in buffer ; | ||
165 | inx ; ; | ||
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 ; | ||
170 | .end ; ; | ||
171 | =over .end local ; | ||
172 | endm ; | ||
173 | ; | ||
174 | ;-----------------------------------------------------------------------; | ||
175 | |||
176 | |||
177 | ; port specific stuff (no data transfer) | ||
178 | |||
179 | DO_PORT macro * port_number | ||
180 | .local ; ; | ||
181 | lda SetUp\1 ; reconfiguration request? ; | ||
182 | .if ne ; yes: ; | ||
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 ; | ||
190 | .end ; ; | ||
191 | ; ; | ||
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 ; | ||
199 | .end ; ; | ||
200 | sta ACIA\1+A_CMD ; set/clear RTS ; | ||
201 | ; ; | ||
202 | lda OutFlush\1 ; request to flush output buffer; | ||
203 | .if ne ; yessh! ; | ||
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 ; | ||
208 | .end | ||
209 | .end local | ||
210 | endm | ||
211 | |||
212 | |||
213 | DO_DATA macro * port number | ||
214 | .local | ||
215 | lda ACIA\1+A_SR ; read ACIA status register ; | ||
216 | biti [1<<3] ; something received? ; | ||
217 | .if ne ; yes: ; | ||
218 | biti [1<<1] ; framing error? ; | ||
219 | .if ne ; yes: ; | ||
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 ; | ||
227 | inx ; ; | ||
228 | cpx InTail\1 ; still room in buffer? ; | ||
229 | .if ne ; absolutely: ; | ||
230 | stx InHead\1 ; update index in memory ; | ||
231 | .end ; ; | ||
232 | jmp =SEND ; go check if anything to send ; | ||
233 | .end ; ; | ||
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 ; | ||
239 | inx ; ; | ||
240 | cpx InTail\1 ; buffer full? ; | ||
241 | .if ne ; no: preserve character: ; | ||
242 | stx InHead\1 ; update index in RAM ; | ||
243 | .end ; ; | ||
244 | and #$7f ; mask off parity if any ; | ||
245 | cmp #XOFF ; XOFF from remote host? ; | ||
246 | .if eq ; yes: ; | ||
247 | lda XonOff\1 ; if XON/XOFF handshaking.. ; | ||
248 | sta OutDisable\1 ; ..disable transmitter ; | ||
249 | .end ; ; | ||
250 | .end ; ; | ||
251 | ; ; | ||
252 | ; BUFFER FULL CHECK WAS HERE ; | ||
253 | ; ; | ||
254 | =SEND lda ACIA\1+A_SR ; transmit register empty? ; | ||
255 | and #[1<<4] ; ; | ||
256 | .if ne ; yes: ; | ||
257 | ldx OutCtrl\1 ; sending out XON/XOFF? ; | ||
258 | .if ne ; yes: ; | ||
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 ; | ||
265 | .end ; ; | ||
266 | ; ; | ||
267 | ldx OutTail\1 ; anything to transmit? ; | ||
268 | cpx OutHead\1 ; ; | ||
269 | .if ne ; yes: ; | ||
270 | lda OutDisable\1 ; allowed to transmit? ; | ||
271 | .if eq ; yes: ; | ||
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 ; | ||
278 | .end ; ; | ||
279 | .end ; ; | ||
280 | .end ; ; | ||
281 | =DONE .end local | ||
282 | endm | ||
283 | |||
284 | |||
285 | |||
286 | PORTVAR macro * port number | ||
287 | VARDEF InHead\1 1 | ||
288 | VARDEF InTail\1 1 | ||
289 | VARDEF OutDisable\1 1 | ||
290 | VARDEF OutHead\1 1 | ||
291 | VARDEF OutTail\1 1 | ||
292 | VARDEF OutCtrl\1 1 | ||
293 | VARDEF OutFlush\1 1 | ||
294 | VARDEF SetUp\1 1 | ||
295 | VARDEF Param\1 1 | ||
296 | VARDEF Command\1 1 | ||
297 | VARDEF SoftFlow\1 1 | ||
298 | ; private: | ||
299 | VARDEF XonOff\1 1 | ||
300 | endm | ||
301 | |||
302 | |||
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 | ||
311 | |||
312 | |||
313 | |||
314 | VARDEF Crystal 1 ; 0 = unknown, 1 = normal, 2 = turbo | ||
315 | VARDEF Pad_a 1 | ||
316 | VARDEF TimerH 1 | ||
317 | VARDEF TimerL 1 | ||
318 | VARDEF CDHead 1 | ||
319 | VARDEF CDTail 1 | ||
320 | VARDEF CDStatus 1 | ||
321 | VARDEF Pad_b 1 | ||
322 | |||
323 | VARDEF CommonCDo 1 ; for carrier detect optimization | ||
324 | VARDEF CommonCDc 1 ; for carrier detect debouncing | ||
325 | VARDEF CommonCDb 1 ; for carrier detect debouncing | ||
326 | |||
327 | |||
328 | VARBASE $0200 | ||
329 | VARDEF obuf0 256 ; output data (characters only) | ||
330 | VARDEF obuf1 256 | ||
331 | VARDEF obuf2 256 | ||
332 | VARDEF obuf3 256 | ||
333 | VARDEF obuf4 256 | ||
334 | VARDEF obuf5 256 | ||
335 | VARDEF obuf6 256 | ||
336 | |||
337 | VARDEF ibuf0 256 ; input data (characters, events etc - see ictl) | ||
338 | VARDEF ibuf1 256 | ||
339 | VARDEF ibuf2 256 | ||
340 | VARDEF ibuf3 256 | ||
341 | VARDEF ibuf4 256 | ||
342 | VARDEF ibuf5 256 | ||
343 | VARDEF ibuf6 256 | ||
344 | |||
345 | VARDEF ictl0 256 ; input control information (type of data in ibuf) | ||
346 | VARDEF ictl1 256 | ||
347 | VARDEF ictl2 256 | ||
348 | VARDEF ictl3 256 | ||
349 | VARDEF ictl4 256 | ||
350 | VARDEF ictl5 256 | ||
351 | VARDEF ictl6 256 | ||
352 | |||
353 | VARDEF cdbuf 256 ; CD event queue | ||
354 | |||
355 | |||
356 | ACIA0 equ $4400 | ||
357 | ACIA1 equ $4c00 | ||
358 | ACIA2 equ $5400 | ||
359 | ACIA3 equ $5c00 | ||
360 | ACIA4 equ $6400 | ||
361 | ACIA5 equ $6c00 | ||
362 | ACIA6 equ $7400 | ||
363 | |||
364 | A_DATA equ $00 | ||
365 | A_SR equ $02 | ||
366 | A_CMD equ $04 | ||
367 | A_CTRL equ $06 | ||
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 | ||
372 | |||
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 | ||
379 | C_TAH equ $0a | ||
380 | C_TBL equ $0c ; timer B | ||
381 | C_TBH equ $0e | ||
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 | ||
389 | |||
390 | |||
391 | |||
392 | |||
393 | |||
394 | section main,code,CODE-2 | ||
395 | |||
396 | db >CODE,<CODE | ||
397 | |||
398 | ;-----------------------------------------------------------------------; | ||
399 | ; here's the initialization code: ; | ||
400 | ; ; | ||
401 | R_RESET ldx #$ff ; | ||
402 | txs ; initialize stack pointer ; | ||
403 | cld ; in case a 6502 is used... ; | ||
404 | ldx #0 ; ; | ||
405 | lda #0 ; ; | ||
406 | ldy #Crystal ; this many bytes to clear ; | ||
407 | clr_loop sta 0,x ; clear zero page variables ; | ||
408 | inx ; ; | ||
409 | dey ; ; | ||
410 | bne clr_loop ; ; | ||
411 | ; ; | ||
412 | stz CommonCDo ; force CD test at boot ; | ||
413 | stz CommonCDb ; ; | ||
414 | stz CDHead ; clear queue ; | ||
415 | stz CDTail ; ; | ||
416 | ; ; | ||
417 | lda #0 ; ; | ||
418 | sta Pad_a ; ; | ||
419 | lda #170 ; test cmp ; | ||
420 | cmp #100 ; ; | ||
421 | .if cs ; ; | ||
422 | inc Pad_a ; C was set ; | ||
423 | .end ; ; | ||
424 | ; | ||
425 | ;-----------------------------------------------------------------------; | ||
426 | ; Speed check ; | ||
427 | ;-----------------------------------------------------------------------; | ||
428 | ; | ||
429 | lda Crystal ; speed already set? ; | ||
430 | beq DoSpeedy ; ; | ||
431 | jmp LOOP ; yes, skip speed test ; | ||
432 | ; ; | ||
433 | DoSpeedy lda #%10011000 ; 8N1, 1200/2400 bps ; | ||
434 | sta ACIA0+A_CTRL ; ; | ||
435 | lda #%00001011 ; enable DTR ; | ||
436 | sta ACIA0+A_CMD ; ; | ||
437 | lda ACIA0+A_SR ; read status register ; | ||
438 | ; ; | ||
439 | lda #%10000000 ; disable all ints (unnecessary); | ||
440 | sta CIA+C_INTCTRL ; ; | ||
441 | lda #255 ; program the timer ; | ||
442 | sta CIA+C_TAL ; ; | ||
443 | sta CIA+C_TAH ; ; | ||
444 | ; ; | ||
445 | ldx #0 ; ; | ||
446 | stx ACIA0+A_DATA ; transmit a zero ; | ||
447 | nop ; ; | ||
448 | nop ; ; | ||
449 | lda ACIA0+A_SR ; read status ; | ||
450 | nop ; ; | ||
451 | nop ; ; | ||
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 ; | ||
456 | ; ; | ||
457 | lda #%00010001 ; load & start the timer ; | ||
458 | stx ACIA0+A_DATA ; transmit one more zero ; | ||
459 | sta CIA+C_CTRLA ; ; | ||
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 ; | ||
464 | ; ; | ||
465 | lda CIA+C_TAL ; copy timer value for 68k ; | ||
466 | sta TimerL ; ; | ||
467 | lda CIA+C_TAH ; ; | ||
468 | sta TimerH ; ; | ||
469 | cmp #$d0 ; turbo or normal? ; | ||
470 | .if cs ; ; | ||
471 | lda #2 ; turbo! :-) ; | ||
472 | .else ; ; | ||
473 | lda #1 ; normal :-( ; | ||
474 | .end ; ; | ||
475 | sta Crystal ; ; | ||
476 | lda #0 ; ; | ||
477 | sta ACIA0+A_SR ; ; | ||
478 | sta ACIA0+A_CTRL ; reset UART ; | ||
479 | sta ACIA0+A_CMD ; ; | ||
480 | ; | ||
481 | jmp LOOP ; | ||
482 | ; | ||
483 | ; ; | ||
484 | ;-----------------------------------------------------------------------; | ||
485 | ; ; | ||
486 | ; The Real Thing: ; | ||
487 | ; ; | ||
488 | LOOP DO_SLOW ; do non-critical things ; | ||
489 | jsr do_input ; check for received data | ||
490 | DO_PORT 0 | ||
491 | jsr do_input | ||
492 | DO_PORT 1 | ||
493 | jsr do_input | ||
494 | DO_PORT 2 | ||
495 | jsr do_input | ||
496 | DO_PORT 3 | ||
497 | jsr do_input | ||
498 | DO_PORT 4 | ||
499 | jsr do_input | ||
500 | DO_PORT 5 | ||
501 | jsr do_input | ||
502 | DO_PORT 6 | ||
503 | jsr do_input | ||
504 | jmp LOOP | ||
505 | |||
506 | |||
507 | do_input DO_DATA 0 | ||
508 | DO_DATA 1 | ||
509 | DO_DATA 2 | ||
510 | DO_DATA 3 | ||
511 | DO_DATA 4 | ||
512 | DO_DATA 5 | ||
513 | DO_DATA 6 | ||
514 | rts | ||
515 | |||
516 | |||
517 | ;-----------------------------------------------------------------------; | ||
518 | section vectors,data,$3ffa | ||
519 | dw $d0d0 | ||
520 | dw R_RESET | ||
521 | dw $c0ce | ||
522 | ;-----------------------------------------------------------------------; | ||
523 | |||
524 | |||
525 | |||
526 | end | ||
527 | |||
528 | |||
529 | |||