linux-old/drivers/char/ser_a2232fw.ax
<<
>>
Prefs
   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
  77CODE            equ     $3800           ; start address for program code
  78
  79
  80CTL_CHAR        equ     $00             ; byte in ibuf is a character
  81CTL_EVENT       equ     $01             ; byte in ibuf is an event
  82
  83EVENT_BREAK     equ     $01
  84EVENT_CDON      equ     $02
  85EVENT_CDOFF     equ     $03
  86EVENT_SYNC      equ     $04
  87
  88XON             equ     $11
  89XOFF            equ     $13
  90
  91
  92VARBASE         macro   *starting_address       ; was VARINIT
  93_varbase        set     \1
  94                endm
  95
  96VARDEF          macro   *name space_needs
  97\1              equ     _varbase
  98_varbase        set     _varbase+\2
  99                endm
 100
 101
 102stz             macro   * address
 103                 db     $64,\1
 104                endm
 105
 106stzax           macro   * address
 107                 db     $9e,<\1,>\1
 108                endm
 109
 110
 111biti            macro   * immediate value
 112                db      $89,\1
 113                endm
 114
 115smb0            macro   * address
 116                db      $87,\1
 117                endm
 118smb1            macro   * address
 119                db      $97,\1
 120                endm
 121smb2            macro   * address
 122                db      $a7,\1
 123                endm
 124smb3            macro   * address
 125                db      $b7,\1
 126                endm
 127smb4            macro   * address
 128                db      $c7,\1
 129                endm
 130smb5            macro   * address
 131                db      $d7,\1
 132                endm
 133smb6            macro   * address
 134                db      $e7,\1
 135                endm
 136smb7            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;                                                                       ;
 146DO_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
 179DO_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
 213DO_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
 286PORTVAR         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
 356ACIA0           equ     $4400
 357ACIA1           equ     $4c00
 358ACIA2           equ     $5400
 359ACIA3           equ     $5c00
 360ACIA4           equ     $6400
 361ACIA5           equ     $6c00
 362ACIA6           equ     $7400
 363
 364A_DATA          equ     $00
 365A_SR            equ     $02
 366A_CMD           equ     $04
 367A_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
 373CIA             equ     $7c00           ; 8520 CIA
 374C_PA            equ     $00             ; port A data register
 375C_PB            equ     $02             ; port B data register
 376C_DDRA          equ     $04             ; data direction register for port A
 377C_DDRB          equ     $06             ; data direction register for port B
 378C_TAL           equ     $08             ; timer A
 379C_TAH           equ     $0a
 380C_TBL           equ     $0c             ; timer B
 381C_TBH           equ     $0e
 382C_TODL          equ     $10             ; TOD LSB
 383C_TODM          equ     $12             ; TOD middle byte
 384C_TODH          equ     $14             ; TOD MSB
 385C_DATA          equ     $18             ; serial data register
 386C_INTCTRL       equ     $1a             ; interrupt control register
 387C_CTRLA         equ     $1c             ; control register A
 388C_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;                                                                       ;
 401R_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      ;
 407clr_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                                        ;                               ;
 433DoSpeedy        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               ;
 453Speedy1         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     ;                               ;
 460Speedy2         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;                                                                       ;
 488LOOP            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
 507do_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
 530
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.