pcmcia: CompactFlash driver for PA Semi Electra boards
[pv_ops_mirror.git] / drivers / char / ser_a2232fw.ax
blob7364380327687d120f48c191453671639068559d
1 ;.lib "axm"
3 ;begin
4 ;title "A2232 serial board driver"
6 ;set modules "2232"
7 ;set executable "2232.bin"
9 ;;;;set nolink
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
16 ;end
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
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.
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.
62 ; Bugs:
64 ; - Can't send a break yet
68 ; Edited:
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.
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
83 EVENT_BREAK     equ     $01
84 EVENT_CDON      equ     $02
85 EVENT_CDOFF     equ     $03
86 EVENT_SYNC      equ     $04
88 XON             equ     $11
89 XOFF            equ     $13
92 VARBASE         macro   *starting_address       ; was VARINIT
93 _varbase        set     \1
94                 endm
96 VARDEF          macro   *name space_needs
97 \1              equ     _varbase
98 _varbase        set     _varbase+\2
99                 endm
102 stz             macro   * address
103                  db     $64,\1
104                 endm
106 stzax           macro   * address
107                  db     $9e,<\1,>\1
108                 endm
111 biti            macro   * immediate value
112                 db      $89,\1
113                 endm
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
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 ;-----------------------------------------------------------------------;
177 ; port specific stuff (no data transfer)
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
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
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
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
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
323  VARDEF CommonCDo 1     ; for carrier detect optimization
324  VARDEF CommonCDc 1     ; for carrier detect debouncing
325  VARDEF CommonCDb 1     ; for carrier detect debouncing
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
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
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
353  VARDEF cdbuf 256       ; CD event queue
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
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
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
394                 section main,code,CODE-2
396                 db      >CODE,<CODE
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
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
517 ;-----------------------------------------------------------------------;
518                 section vectors,data,$3ffa
519                 dw      $d0d0
520                 dw      R_RESET
521                 dw      $c0ce
522 ;-----------------------------------------------------------------------;
526                 end