Changeset 4f508e6 in buchla-68k for ram/serintr.s


Ignore:
Timestamp:
07/01/2017 02:34:46 PM (7 years ago)
Author:
Thomas Lopatic <thomas@…>
Branches:
master
Children:
08e1da1
Parents:
f40a309
Message:

Converted assembly language files.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • ram/serintr.s

    rf40a309 r4f508e6  
    1 * ------------------------------------------------------------------------------
    2 * serintr.s -- MIDAS-VII serial I/O subroutines
    3 * Version 4 -- 1988-12-13 -- D.N. Lynx Crowe
    4 *
    5 * These subroutines replace those in bios.s in order to add support for
    6 * MIDAS-VII foot pedal and pulse inputs, and pulse outputs.
    7 *
    8 * WARNING:  The code below uses addresses in the bios RAM area.  These addresses
    9 * correspond to those in PROMS dated 1988-06-20 et seq.  If the bios is changed,
    10 * the addresses marked with <== may have to be changed.
    11 * ------------------------------------------------------------------------------
    12 *
     1| ------------------------------------------------------------------------------
     2| serintr.s -- MIDAS-VII serial I/O subroutines
     3| Version 4 -- 1988-12-13 -- D.N. Lynx Crowe
     4
     5| These subroutines replace those in bios.s in order to add support for
     6| MIDAS-VII foot pedal and pulse inputs, and pulse outputs.
     7
     8| WARNING:  The code below uses addresses in the bios RAM area.  These addresses
     9| correspond to those in PROMS dated 1988-06-20 et seq.  If the bios is changed,
     10| the addresses marked with <== may have to be changed.
     11| ------------------------------------------------------------------------------
     12
    1313                .text
    14 *
     14
    1515                .xdef   _setsio
    16 *
     16
    1717                .xdef   _foot1
    1818                .xdef   _foot2
    1919                .xdef   _pulse1
    2020                .xdef   _pulse2
    21 *
     21
    2222                .xdef   serintr
    23 *
     23
    2424                .xdef   serint
    2525                .xdef   midint
    26 *
     26
    2727                .xdef   wrapin
    2828                .xdef   wrapout
    29 *
     29
    3030                .xdef   serput
    3131                .xdef   midput
    32 *
     32
    3333                .xdef   rtschk
    34 *
     34
    3535                .xdef   rtson
    3636                .xdef   rtsoff
    37 *
    38 * ==============================================================================
    39 *
    40 * The following addresses, marked by <==, are bios version dependent:
    41 *
    42 RAM             .equ    $00000400       * Beginning of system RAM area  <==
    43 *
    44 SR1IOREC        .equ    RAM+$0AB0       * Serial-1 iorec structure      <==
    45 SR2IOREC        .equ    RAM+$0AD8       * Serial-2 iorec structure      <==
    46 MC1IOREC        .equ    RAM+$0B00       * MIDI-1 iorec structure        <==
    47 MC2IOREC        .equ    RAM+$0B28       * MIDI-2 iorec structure        <==
    48 *
    49 * End of bios version dependent addresses.
    50 *
    51 * ==============================================================================
    52 *
    53                 .page
    54 *
    55 SERVECT         .equ    $000074         * Level 5 interrupt autovector address
    56 *
    57 IPL7            .equ    $0700           * IPL 7 value for sr
    58 *
    59 * ACIA I/O Addresses:
    60 * -------------------
    61 SR1ACIA         .equ    $3A8001         * Serial-1 ACIA base address
    62 SR2ACIA         .equ    $3A8009         * Serial-2 ACIA base address
    63 MC1ACIA         .equ    $3AC001         * MIDI-1 ACIA base address
    64 MC2ACIA         .equ    $3AC009         * MIDI-2 ACIA base address
    65 *
    66 * ACIA Register offsets:
    67 * ----------------------
    68 ACIA_IER        .equ    0               * ACIA IER offset
    69 ACIA_ISR        .equ    0               * ACIA ISR offset
    70 ACIA_CSR        .equ    2               * ACIA CSR offset
    71 ACIA_CFR        .equ    2               * ACIA CFR offset
    72 ACIA_TBR        .equ    4               * ACIA TBR offset
    73 ACIA_TDR        .equ    6               * ACIA TDR offset
    74 ACIA_RDR        .equ    6               * ACIA RDR offset
    75 *
    76 * iorec structure definitions:
    77 * ----------------------------
    78 IORECLN         .equ    40              * Length of an iorec structure
    79 *
    80 ibuf            .equ    0               * Input buffer base address
    81 ibufsize        .equ    4               * Input buffer size  (bytes)
    82 ibufhd          .equ    6               * Input buffer head index
    83 ibuftl          .equ    8               * Input buffer tail index
    84 ibuflow         .equ    10              * Input buffer low water mark
    85 ibufhi          .equ    12              * Input buffer high water mark
    86 obuf            .equ    14              * Output buffer base address
    87 obufsize        .equ    18              * Output buffer size  (bytes)
    88 obufhd          .equ    20              * Output buffer head index
    89 obuftl          .equ    22              * Output buffer tail index
    90 obuflow         .equ    24              * Output buffer low water mark
    91 obufhi          .equ    26              * Output buffer high water mark
    92 cfr0            .equ    28              * ACIA CFR, MS bit = 0
    93 cfr1            .equ    29              * ACIA CFR, MS bit = 1
    94 flagxon         .equ    30              * XON flag  (non-zero = XOFF sent)
    95 flagxoff        .equ    31              * XOFF flag  (non-zero = active)
    96 linedisc        .equ    32              * Line discipline flags
    97 erbyte          .equ    33              * Last error byte
    98 isr             .equ    34              * ACIA ISR on interrupt
    99 csr             .equ    35              * ACIA CSR on interrupt
    100 errct           .equ    36              * Error count  (FRM/OVR/BRK)
    101 ibfct           .equ    38              * Input buffer full count
    102 *
    103                 .page
    104 *
    105 * serintr -- Serial (Serial-1, Serial-2, MIDI-1, MIDI-2) interrupt handler
    106 * -------    -------------------------------------------------------------
    107 serintr:        movem.l d0-d3/a0-a2,-(a7)       * Save registers
    108                 lea     SR1IOREC,a0             * Point at Serial-1 iorec
    109                 lea     SR1ACIA,a1              * Point at Serial-1 ACIA
    110                 movea.l _foot1,a2               * Point at foot sw. 1 processor
    111                 bsr     serint                  * Go process (possible) int.
    112 *
    113                 lea     SR2IOREC,a0             * Point at Serial-2 iorec
    114                 lea     SR2ACIA,a1              * Point at Serial-2 ACIA
    115                 movea.l _foot2,a2               * Point at foot sw. 2 processor
    116                 bsr     serint                  * Go process (possible) int.
    117 *
    118                 lea     MC1IOREC,a0             * Point at MIDI-1 iorec
    119                 lea     MC1ACIA,a1              * Point at MIDI-1 ACIA
    120                 movea.l _pulse1,a2              * Point at pulse 1 processor
    121                 bsr     midint                  * Go process (possible) int.
    122 *
    123                 lea     MC2IOREC,a0             * Point at MIDI-2 iorec
    124                 lea     MC2ACIA,a1              * Point at MIDI-2 ACIA
    125                 movea.l _pulse2,a2              * Point at pulse 2 processor
    126                 bsr     midint                  * Go process (possible) int.
    127 *
    128                 movem.l (a7)+,d0-d3/a0-a2       * Restore registers
    129                 rte                             * Return from exception
    130 *
    131                 .page
    132 *
    133 * serint -- Process an interrupt from Serial-1 or Serial-2
    134 * ------    ----------------------------------------------
    135 serint:         move.b  ACIA_ISR(a1),isr(a0)    * Get and save ISR
    136                 move.b  ACIA_CSR(a1),csr(a0)    * Get and save CSR
    137 *
    138                 btst.b  #7,isr(a0)              * Was int for this device ?
    139                 beq     serintx                 * Jump if not
    140 *
    141 serchk:         btst.b  #1,isr(a0)              * FRM/OVR/BRK error ?
    142                 bne     sererr                  * Jump if so
    143 *
    144                 btst.b  #0,isr(a0)              * Receiver interrupt ?
    145                 bne     serrx                   * Jump if so
    146 *
    147 sertxq:         btst.b  #6,isr(a0)              * Transmitter interrupt ?
    148                 bne     sertx                   * Jump if so
    149 *
    150 serctq:         btst.b  #5,isr(a0)              * CTS interrupt ?
    151                 bne     sercts                  * Jump if so
    152 *
    153 serintx:        btst.b  #4,isr(a0)              * DCD interrupt ?
    154                 bne     calldcd                 * Jump if so
    155 *
    156 serdone:        rts                             * Return to caller
    157 *
    158 calldcd:        move.b  csr(a0),d0              * Get CSR interrupt status
    159                 btst.l  #4,d0                   * Check DCD input  (0 = active)
    160                 bne     calldcd0                * Jump if line was inactive
    161 *
    162                 moveq.l #1,d0                   * Set footswitch status to TRUE
    163                 bra     calldcd1                * ...
    164 *
    165 calldcd0:       moveq.l #0,d0                   * Set footswitch status to FALSE
    166 *
    167 calldcd1:       move.w  d0,-(a7)                * Call the footswitch processor
    168                 jsr     (a2)                    * ... (*footX)(status)
    169                 tst.w   (a7)+                   * ...
    170                 rts                             * Return to caller
    171 *
    172                 .page
    173 *
    174 * Handle serial I/O port error
    175 *
    176 sererr:         addq.w  #1,errct(a0)            * Update error count
    177                 move.b  ACIA_RDR(a1),erbyte(a0) * Get error byte
    178                 rts                             * Return to caller
    179 *
    180 *
    181 * Handle CTS interupt
    182 *
    183 sercts:         btst.b  #1,linedisc(a0)         * RTS/CTS mode ?
    184                 beq     serintx                 * Ignore if not
    185 *
    186                 btst.b  #5,csr(a0)              * CTS set ?
    187                 beq     serintx                 * Ignore if not
    188 *
    189 sercts1:        btst.b  #6,isr(a0)              * TDRE set ?
    190                 beq     sercts1                 * Loop until it is  (!)
    191 *
    192                 move.w  obufhd(a0),d2           * Head index to d2
    193                 cmp.w   obuftl(a0),d2           * Compare to tail index
    194                 beq     serintx                 * Done if buffer empty
    195 *
    196                 bsr     wrapout                 * Adjust pointer for wraparound
    197                 move.l  obuf(a0),a2             * Get buffer base in a2
    198                 move.b  0(a2,d2),ACIA_TDR(a1)   * Send byte on its way
    199                 move.w  d2,obufhd(a0)           * Save updated head index
    200                 bra     serintx                 * Done
    201 *
    202                 .page
    203 *
    204 * Handle receiver interrupt
    205 *
    206 serrx:          btst.b  #1,linedisc(a0)         * RTS/CTS mode set ?
    207                 beq     serrx1                  * Jump if not
    208 *
    209                 bsr     rtsoff                  * Turn off RTS
    210 *
    211 serrx1:         move.b  ACIA_RDR(a1),d0         * Read data from ACIA
    212                 btst.b  #1,linedisc(a0)         * RTS/CTS mode set ?
    213                 bne     serrx3                  * Jump if so
    214 *
    215                 btst.b  #0,linedisc(a0)         * XON/XOFF mode set ?
    216                 beq     serrx3                  * Jump if not
    217 *
    218                 cmpi.b  #$11,d0                 * Is this an XON ?
    219                 bne     serrx2                  * Jump if not
    220 *
    221                 move.b  #$00,flagxoff(a0)       * Clear flagxoff
    222                 bra     sertxq                  * Done
    223 *
    224 serrx2:         cmpi.b  #$13,d0                 * Is this an XOFF ?
    225                 bne     serrx3                  * Jump if not
    226 *
    227                 move.b  #$FF,flagxoff(a0)       * Set flagxoff
    228                 bra     sertxq                  * Done
    229 *
    230 serrx3:         move.w  ibuftl(a0),d1           * Get tail index in d1
    231                 bsr     wrapin                  * Adjust for wraparound
    232                 cmp.w   ibufhd(a0),d1           * Head = tail ?
    233                 beq     seribf                  * If so, we drop the character
    234 *
    235                 .page
    236                 move.l  ibuf(a0),a2             * Get buffer address
    237                 move.b  d0,0(a2,d1)             * Stash byte in buffer
    238                 move.w  d1,ibuftl(a0)           * Save updated tail index
    239                 move.w  ibuftl(a0),d2           * Tail index to d2
    240                 move.w  ibufhd(a0),d3           * Head index to d3
    241                 cmp.w   d3,d2                   * Head > Tail ?
    242                 bhi     rsi_1                   * Jump if not
    243 *
    244                 add.w   ibufsize(a0),d2         * Add buffer size to tail index
    245 *
    246 rsi_1:          sub.w   d3,d2                   * Length = (adjusted)Tail - Head
    247                 cmp.w   ibufhi(a0),d2           * Hit high water mark ?
    248                 bne     serrx4                  * Jump if not
    249 *
    250                 btst.b  #1,linedisc(a0)         * RTS/CTS mode set ?
    251                 bne     sertxq                  * Done if so
    252 *
    253                 btst.b  #0,linedisc(a0)         * XON/XOFF mode set ?
    254                 beq     serrx4                  * Jump if not
    255 *
    256                 tst.b   flagxon(a0)             * XOFF already sent ?
    257                 bne     serrx4                  * Jump if so
    258 *
    259                 move.b  #$FF,flagxon(a0)        * Set the flag
    260                 move.b  #$13,d1                 * Send an XOFF
    261                 bsr     serput                  * ...
    262 *
    263 serrx4:         btst    #1,linedisc(a0)         * RTS/CTS mode set ?
    264                 beq     sertxq                  * Done if not
    265 *
    266                 bsr     rtson                   * Turn on RTS
    267                 bra     sertxq                  * Done
    268 *
    269                 .page
    270 *
    271 * Handle transmitter interrupt
    272 *
    273 sertx:          btst.b  #1,linedisc(a0)         * RTS/CTS mode set ?
    274                 bne     sertx2                  * If so, go check CTS
    275 *
    276                 btst.b  #0,linedisc(a0)         * XON/XOFF mode set ?
    277                 beq     sertx1                  * Jump if not
    278 *
    279                 tst.b   flagxoff(a0)            * Check flagxoff
    280                 bne     serctq                  * Done if set
    281 *
    282 sertx1:         move.w  obufhd(a0),d2           * Head index to d2
    283                 cmp.w   obuftl(a0),d2           * Compare to tail index
    284                 beq     serctq                  * Done if buffer empty
    285 *
    286                 bsr     wrapout                 * Adjust pointer for wraparound
    287                 move.l  obuf(a0),a2             * Get buffer base address
    288                 move.b  0(a2,d2),ACIA_TDR(a1)   * Send byte on its way
    289                 move.w  d2,obufhd(a0)           * Save updated head index
    290                 bra     serctq                  * Done
    291 *
    292 sertx2:         btst.b  #5,csr(a0)              * CTS set in csr ?
    293                 beq     serctq                  * If not, go check for CTS int
    294 *
    295                 bra     sertx1                  * CTS was set, go transmit
    296 *
    297 seribf:         move.b  d0,erbyte(a0)           * Log dropped character
    298                 addq.w  #1,ibfct(a0)            * ...
    299                 bra     sertxq                  * Go check Tx interrupt
    300 *
    301                 .page
    302 *
    303 * midint -- Process an interrupt from MIDI-1 or MIDI-2
    304 * ------    ------------------------------------------
    305 midint:         move.b  ACIA_ISR(a1),isr(a0)    * Get and save ISR
    306                 move.b  ACIA_CSR(a1),csr(a0)    * Get and save CSR
    307 *
    308                 btst.b  #7,isr(a0)              * Was int for this device ?
    309                 beq     midintx                 * Jump if not
    310 *
    311 midchk:         btst.b  #1,isr(a0)              * FRM/OVR/BRK error ?
    312                 bne     miderr                  * Jump if so
    313 *
    314                 btst.b  #0,isr(a0)              * Receiver interrupt ?
    315                 bne     midrx                   * Jump if so
    316 *
    317 midtxq:         btst.b  #6,isr(a0)              * Transmitter interrupt ?
    318                 bne     midtx                   * Jump if so
    319 *
    320 midintx:        btst    #4,isr(a0)              * DCD interrupt ?
    321                 bne     mididcd                 * Jump if so
    322 *
    323 mididone:       rts                             * Return to caller
    324 *
    325 mididcd:        jmp     (a2)                    * Exit through the DCD processor
    326 *
    327 miderr:         addq.w  #1,errct(a0)            * Update error count
    328                 move.b  ACIA_RDR(a1),erbyte(a0) * Get error byte
     37
     38| ==============================================================================
     39
     40| The following addresses, marked by <==, are bios version dependent:
     41
     42RAM             =       0x00000400      | Beginning of system RAM area  <==
     43
     44SR1IOREC        =       RAM+0x0AB0      | Serial-1 iorec structure      <==
     45SR2IOREC        =       RAM+0x0AD8      | Serial-2 iorec structure      <==
     46MC1IOREC        =       RAM+0x0B00      | MIDI-1 iorec structure        <==
     47MC2IOREC        =       RAM+0x0B28      | MIDI-2 iorec structure        <==
     48
     49| End of bios version dependent addresses.
     50
     51| ==============================================================================
     52
     53                .page
     54
     55SERVECT         =       0x000074        | Level 5 interrupt autovector address
     56
     57IPL7            =       0x0700          | IPL 7 value for sr
     58
     59| ACIA I/O Addresses:
     60| -------------------
     61SR1ACIA         =       0x3A8001        | Serial-1 ACIA base address
     62SR2ACIA         =       0x3A8009        | Serial-2 ACIA base address
     63MC1ACIA         =       0x3AC001        | MIDI-1 ACIA base address
     64MC2ACIA         =       0x3AC009        | MIDI-2 ACIA base address
     65
     66| ACIA Register offsets:
     67| ----------------------
     68ACIA_IER        =       0               | ACIA IER offset
     69ACIA_ISR        =       0               | ACIA ISR offset
     70ACIA_CSR        =       2               | ACIA CSR offset
     71ACIA_CFR        =       2               | ACIA CFR offset
     72ACIA_TBR        =       4               | ACIA TBR offset
     73ACIA_TDR        =       6               | ACIA TDR offset
     74ACIA_RDR        =       6               | ACIA RDR offset
     75
     76| iorec structure definitions:
     77| ----------------------------
     78IORECLN         =       40              | Length of an iorec structure
     79
     80ibuf            =       0               | Input buffer base address
     81ibufsize        =       4               | Input buffer size  (bytes)
     82ibufhd          =       6               | Input buffer head index
     83ibuftl          =       8               | Input buffer tail index
     84ibuflow         =       10              | Input buffer low water mark
     85ibufhi          =       12              | Input buffer high water mark
     86obuf            =       14              | Output buffer base address
     87obufsize        =       18              | Output buffer size  (bytes)
     88obufhd          =       20              | Output buffer head index
     89obuftl          =       22              | Output buffer tail index
     90obuflow         =       24              | Output buffer low water mark
     91obufhi          =       26              | Output buffer high water mark
     92cfr0            =       28              | ACIA CFR, MS bit = 0
     93cfr1            =       29              | ACIA CFR, MS bit = 1
     94flagxon         =       30              | XON flag  (non-zero = XOFF sent)
     95flagxoff        =       31              | XOFF flag  (non-zero = active)
     96linedisc        =       32              | Line discipline flags
     97erbyte          =       33              | Last error byte
     98isr             =       34              | ACIA ISR on interrupt
     99csr             =       35              | ACIA CSR on interrupt
     100errct           =       36              | Error count  (FRM/OVR/BRK)
     101ibfct           =       38              | Input buffer full count
     102
     103                .page
     104
     105| serintr -- Serial (Serial-1, Serial-2, MIDI-1, MIDI-2) interrupt handler
     106| -------    -------------------------------------------------------------
     107serintr:        movem.l d0-d3/a0-a2,-(a7)       | Save registers
     108                lea     SR1IOREC,a0             | Point at Serial-1 iorec
     109                lea     SR1ACIA,a1              | Point at Serial-1 ACIA
     110                movea.l _foot1,a2               | Point at foot sw. 1 processor
     111                bsr     serint                  | Go process (possible) int.
     112
     113                lea     SR2IOREC,a0             | Point at Serial-2 iorec
     114                lea     SR2ACIA,a1              | Point at Serial-2 ACIA
     115                movea.l _foot2,a2               | Point at foot sw. 2 processor
     116                bsr     serint                  | Go process (possible) int.
     117
     118                lea     MC1IOREC,a0             | Point at MIDI-1 iorec
     119                lea     MC1ACIA,a1              | Point at MIDI-1 ACIA
     120                movea.l _pulse1,a2              | Point at pulse 1 processor
     121                bsr     midint                  | Go process (possible) int.
     122
     123                lea     MC2IOREC,a0             | Point at MIDI-2 iorec
     124                lea     MC2ACIA,a1              | Point at MIDI-2 ACIA
     125                movea.l _pulse2,a2              | Point at pulse 2 processor
     126                bsr     midint                  | Go process (possible) int.
     127
     128                movem.l (a7)+,d0-d3/a0-a2       | Restore registers
     129                rte                             | Return from exception
     130
     131                .page
     132
     133| serint -- Process an interrupt from Serial-1 or Serial-2
     134| ------    ----------------------------------------------
     135serint:         move.b  ACIA_ISR(a1),isr(a0)    | Get and save ISR
     136                move.b  ACIA_CSR(a1),csr(a0)    | Get and save CSR
     137
     138                btst.b  #7,isr(a0)              | Was int for this device ?
     139                beq     serintx                 | Jump if not
     140
     141serchk:         btst.b  #1,isr(a0)              | FRM/OVR/BRK error ?
     142                bne     sererr                  | Jump if so
     143
     144                btst.b  #0,isr(a0)              | Receiver interrupt ?
     145                bne     serrx                   | Jump if so
     146
     147sertxq:         btst.b  #6,isr(a0)              | Transmitter interrupt ?
     148                bne     sertx                   | Jump if so
     149
     150serctq:         btst.b  #5,isr(a0)              | CTS interrupt ?
     151                bne     sercts                  | Jump if so
     152
     153serintx:        btst.b  #4,isr(a0)              | DCD interrupt ?
     154                bne     calldcd                 | Jump if so
     155
     156serdone:        rts                             | Return to caller
     157
     158calldcd:        move.b  csr(a0),d0              | Get CSR interrupt status
     159                btst.l  #4,d0                   | Check DCD input  (0 = active)
     160                bne     calldcd0                | Jump if line was inactive
     161
     162                moveq.l #1,d0                   | Set footswitch status to TRUE
     163                bra     calldcd1                | ...
     164
     165calldcd0:       moveq.l #0,d0                   | Set footswitch status to FALSE
     166
     167calldcd1:       move.w  d0,-(a7)                | Call the footswitch processor
     168                jsr     (a2)                    | ... (|footX)(status)
     169                tst.w   (a7)+                   | ...
     170                rts                             | Return to caller
     171
     172                .page
     173
     174| Handle serial I/O port error
     175
     176sererr:         addq.w  #1,errct(a0)            | Update error count
     177                move.b  ACIA_RDR(a1),erbyte(a0) | Get error byte
     178                rts                             | Return to caller
     179
     180
     181| Handle CTS interupt
     182
     183sercts:         btst.b  #1,linedisc(a0)         | RTS/CTS mode ?
     184                beq     serintx                 | Ignore if not
     185
     186                btst.b  #5,csr(a0)              | CTS set ?
     187                beq     serintx                 | Ignore if not
     188
     189sercts1:        btst.b  #6,isr(a0)              | TDRE set ?
     190                beq     sercts1                 | Loop until it is  (!)
     191
     192                move.w  obufhd(a0),d2           | Head index to d2
     193                cmp.w   obuftl(a0),d2           | Compare to tail index
     194                beq     serintx                 | Done if buffer empty
     195
     196                bsr     wrapout                 | Adjust pointer for wraparound
     197                move.l  obuf(a0),a2             | Get buffer base in a2
     198                move.b  0(a2,d2),ACIA_TDR(a1)   | Send byte on its way
     199                move.w  d2,obufhd(a0)           | Save updated head index
     200                bra     serintx                 | Done
     201
     202                .page
     203
     204| Handle receiver interrupt
     205
     206serrx:          btst.b  #1,linedisc(a0)         | RTS/CTS mode set ?
     207                beq     serrx1                  | Jump if not
     208
     209                bsr     rtsoff                  | Turn off RTS
     210
     211serrx1:         move.b  ACIA_RDR(a1),d0         | Read data from ACIA
     212                btst.b  #1,linedisc(a0)         | RTS/CTS mode set ?
     213                bne     serrx3                  | Jump if so
     214
     215                btst.b  #0,linedisc(a0)         | XON/XOFF mode set ?
     216                beq     serrx3                  | Jump if not
     217
     218                cmpi.b  #0x11,d0                | Is this an XON ?
     219                bne     serrx2                  | Jump if not
     220
     221                move.b  #0x00,flagxoff(a0)      | Clear flagxoff
     222                bra     sertxq                  | Done
     223
     224serrx2:         cmpi.b  #0x13,d0                | Is this an XOFF ?
     225                bne     serrx3                  | Jump if not
     226
     227                move.b  #0xFF,flagxoff(a0)      | Set flagxoff
     228                bra     sertxq                  | Done
     229
     230serrx3:         move.w  ibuftl(a0),d1           | Get tail index in d1
     231                bsr     wrapin                  | Adjust for wraparound
     232                cmp.w   ibufhd(a0),d1           | Head = tail ?
     233                beq     seribf                  | If so, we drop the character
     234
     235                .page
     236                move.l  ibuf(a0),a2             | Get buffer address
     237                move.b  d0,0(a2,d1)             | Stash byte in buffer
     238                move.w  d1,ibuftl(a0)           | Save updated tail index
     239                move.w  ibuftl(a0),d2           | Tail index to d2
     240                move.w  ibufhd(a0),d3           | Head index to d3
     241                cmp.w   d3,d2                   | Head > Tail ?
     242                bhi     rsi_1                   | Jump if not
     243
     244                add.w   ibufsize(a0),d2         | Add buffer size to tail index
     245
     246rsi_1:          sub.w   d3,d2                   | Length = (adjusted)Tail - Head
     247                cmp.w   ibufhi(a0),d2           | Hit high water mark ?
     248                bne     serrx4                  | Jump if not
     249
     250                btst.b  #1,linedisc(a0)         | RTS/CTS mode set ?
     251                bne     sertxq                  | Done if so
     252
     253                btst.b  #0,linedisc(a0)         | XON/XOFF mode set ?
     254                beq     serrx4                  | Jump if not
     255
     256                tst.b   flagxon(a0)             | XOFF already sent ?
     257                bne     serrx4                  | Jump if so
     258
     259                move.b  #0xFF,flagxon(a0)       | Set the flag
     260                move.b  #0x13,d1                | Send an XOFF
     261                bsr     serput                  | ...
     262
     263serrx4:         btst    #1,linedisc(a0)         | RTS/CTS mode set ?
     264                beq     sertxq                  | Done if not
     265
     266                bsr     rtson                   | Turn on RTS
     267                bra     sertxq                  | Done
     268
     269                .page
     270
     271| Handle transmitter interrupt
     272
     273sertx:          btst.b  #1,linedisc(a0)         | RTS/CTS mode set ?
     274                bne     sertx2                  | If so, go check CTS
     275
     276                btst.b  #0,linedisc(a0)         | XON/XOFF mode set ?
     277                beq     sertx1                  | Jump if not
     278
     279                tst.b   flagxoff(a0)            | Check flagxoff
     280                bne     serctq                  | Done if set
     281
     282sertx1:         move.w  obufhd(a0),d2           | Head index to d2
     283                cmp.w   obuftl(a0),d2           | Compare to tail index
     284                beq     serctq                  | Done if buffer empty
     285
     286                bsr     wrapout                 | Adjust pointer for wraparound
     287                move.l  obuf(a0),a2             | Get buffer base address
     288                move.b  0(a2,d2),ACIA_TDR(a1)   | Send byte on its way
     289                move.w  d2,obufhd(a0)           | Save updated head index
     290                bra     serctq                  | Done
     291
     292sertx2:         btst.b  #5,csr(a0)              | CTS set in csr ?
     293                beq     serctq                  | If not, go check for CTS int
     294
     295                bra     sertx1                  | CTS was set, go transmit
     296
     297seribf:         move.b  d0,erbyte(a0)           | Log dropped character
     298                addq.w  #1,ibfct(a0)            | ...
     299                bra     sertxq                  | Go check Tx interrupt
     300
     301                .page
     302
     303| midint -- Process an interrupt from MIDI-1 or MIDI-2
     304| ------    ------------------------------------------
     305midint:         move.b  ACIA_ISR(a1),isr(a0)    | Get and save ISR
     306                move.b  ACIA_CSR(a1),csr(a0)    | Get and save CSR
     307
     308                btst.b  #7,isr(a0)              | Was int for this device ?
     309                beq     midintx                 | Jump if not
     310
     311midchk:         btst.b  #1,isr(a0)              | FRM/OVR/BRK error ?
     312                bne     miderr                  | Jump if so
     313
     314                btst.b  #0,isr(a0)              | Receiver interrupt ?
     315                bne     midrx                   | Jump if so
     316
     317midtxq:         btst.b  #6,isr(a0)              | Transmitter interrupt ?
     318                bne     midtx                   | Jump if so
     319
     320midintx:        btst    #4,isr(a0)              | DCD interrupt ?
     321                bne     mididcd                 | Jump if so
     322
     323mididone:       rts                             | Return to caller
     324
     325mididcd:        jmp     (a2)                    | Exit through the DCD processor
     326
     327miderr:         addq.w  #1,errct(a0)            | Update error count
     328                move.b  ACIA_RDR(a1),erbyte(a0) | Get error byte
    329329                rts
    330 *
    331 * Handle receiver interrupt
    332 *
    333 midrx:          move.b  ACIA_RDR(a1),d0         * Read data from ACIA
    334                 move.w  ibuftl(a0),d1           * Get tail index in d1
    335                 bsr     wrapin                  * Adjust for wraparound
    336                 cmp.w   ibufhd(a0),d1           * Head = tail ?
    337                 beq     midibf                  * If so, we drop the character
    338 *
    339                 move.l  ibuf(a0),a2             * Get buffer address
    340                 move.b  d0,0(a2,d1)             * Stash byte in buffer
    341                 move.w  d1,ibuftl(a0)           * Save updated tail index
    342                 bra     midtxq                  * Done  (go check tx int)
    343 *
    344                 .page
    345 *
    346 * Handle transmitter interrupt
    347 *
    348 midtx:          move.w  obufhd(a0),d2           * Head index to d2
    349                 cmp.w   obuftl(a0),d2           * Compare to tail index
    350                 beq     midintx                 * Done if buffer empty
    351 *
    352                 bsr     wrapout                 * Adjust pointer for wraparound
    353                 move.l  obuf(a0),a2             * Get buffer base address
    354                 move.b  0(a2,d2),ACIA_TDR(a1)   * Send byte on its way
    355                 move.w  d2,obufhd(a0)           * Save updated head index
    356                 bra     midintx                 * Done
    357 *
    358 midibf:         move.b  d0,erbyte(a0)           * Log dropped character
    359                 addq.w  #1,ibfct(a0)            * ...
    360                 bra     midtxq                  * Go check Tx interrupt
    361 *
    362                 .page
    363 *
    364 * serput -- Output a character to a serial port
    365 * ------    -----------------------------------
    366 serput:         move.w  sr,-(a7)                * Save status register
    367                 ori.w   #IPL7,sr                * DISABLE INTERRUPTS
    368                 move.b  ACIA_ISR(a1),isr(a0)    * Get ACIA isr
    369                 move.b  ACIA_CSR(a1),csr(a0)    * Get ACIA csr
    370                 btst    #0,linedisc(a0)         * XON/XOFF mode ?
    371                 beq     serpt_1                 * Jump if not
    372 *
    373                 tst.b   flagxoff(a0)            * XON active ?
    374                 bne     serpt_2                 * Jump if so
    375 *
    376 serpt_1:        btst.b  #6,isr(a0)              * Is ACIA still sending ?
    377                 beq     serpt_2                 * Jump if so
    378 *
    379                 move.w  obufhd(a0),d2           * Head index to d2
    380                 cmp.w   obuftl(a0),d2           * Compare to tail index
    381                 bne     serpt_2                 * Jump if buffer not empty
    382 *
    383                 move.b  d1,ACIA_TDR(a1)         * Give byte to ACIA to send
    384                 bra     serpt_3                 * Go deal with RTS/CTS if needed
    385 *
    386 serpt_2:        move.w  obuftl(a0),d2           * Tail index to d2
    387                 bsr     wrapout                 * Adjust for wraparound
    388                 cmp.w   obufhd(a0),d2           * Compare to head index
    389                 beq     serpt_4                 * Jump if buffer full
    390 *
    391                 move.l  obuf(a0),a2             * Get buffer base address in a2
    392                 move.b  d1,0(a2,d2)             * Put character in buffer
    393                 move.w  d2,obuftl(a0)           * Update buffer tail index
    394 *
    395 serpt_3:        bsr     serchk                  * Check status on our way out
    396                 bsr     rtschk                  * Handle RTS protocol
    397                 move.w  (a7)+,sr                * RESTORE INTERRUPTS
    398                 andi    #$FFFE,sr               * Clear carry flag = OK
    399                 rts                             * Return to caller
    400 *
    401 serpt_4:        bsr     serchk                  * Check status on our way out
    402                 bsr     rtschk                  * Handle RTS protocol
    403                 move.w  (a7)+,sr                * RESTORE INTERRUPTS
    404                 ori     #$0001,sr               * Set carry flag = buffer full
    405                 rts                             * Return to caller
    406 *
    407                 .page
    408 *
    409 * midput -- Output to MIDI
    410 * ------    --------------
    411 midput:         move.w  sr,-(a7)                * Save status register
    412                 ori.w   #IPL7,sr                * DISABLE INTERRUPTS
    413                 move.b  ACIA_ISR(a1),isr(a0)    * Get ACIA isr
    414                 move.b  ACIA_CSR(a1),csr(a0)    * Get ACIA csr
    415                 btst.b  #6,isr(a0)              * Is ACIA still sending ?
    416                 beq     midpt_2                 * Jump if so
    417 *
    418                 move.w  obufhd(a0),d2           * Head index to d2
    419                 cmp.w   obuftl(a0),d2           * Compare to tail index
    420                 bne     midpt_2                 * Jump if buffer not empty
    421 *
    422                 move.b  d1,ACIA_TDR(a1)         * Give byte to ACIA to send
    423                 bra     midpt_3                 * Go set final status and exit
    424 *
    425 midpt_2:        move.w  obuftl(a0),d2           * Tail index to d2
    426                 bsr     wrapout                 * Adjust for wraparound
    427                 cmp.w   obufhd(a0),d2           * Compare to head index
    428                 beq     midpt_4                 * Jump if buffer full
    429 *
    430                 move.l  obuf(a0),a2             * Get buffer base address in a2
    431                 move.b  d1,0(a2,d2)             * Put character in buffer
    432                 move.w  d2,obuftl(a0)           * Update buffer tail index
    433 *
    434 midpt_3:        bsr     midchk                  * Check status on our way out
    435                 move.w  (a7)+,sr                * RESTORE INTERRUPTS
    436                 andi    #$FFFE,sr               * Clear carry flag = OK
    437                 rts                             * Return to caller
    438 *
    439 midpt_4:        bsr     midchk                  * Check status on our way out
    440                 move.w  (a7)+,sr                * RESTORE INTERRUPTS
    441                 ori     #$0001,sr               * Set carry flag = buffer full
    442                 rts                             * Return to caller
    443 *
    444                 .page
    445 *
    446 * rtschk -- Check RTS mode and turn on RTS if it's enabled
    447 * ------    ----------------------------------------------
    448 rtschk:         btst    #1,linedisc(a0)         * RTS/CTS mode set ?
    449                 beq     rtsexit                 * Jump to exit if not
    450 *
    451 * rtson -- Turn on RTS line
    452 * -----    ----------------
    453 rtson:          move.b  cfr1(a0),d0             * Pick up CFR1 image
    454                 bclr    #0,d0                   * Turn on RTS line  (0 = on)
    455                 bra     rtscmn                  * Join common RTS code below
    456 *
    457 * rtsoff -- Turn off RTS line
    458 * ------    -----------------
    459 rtsoff:         move.b  cfr1(a0),d0             * Pick up CFR1 image
    460                 bset    #0,d0                   * Turn off RTS line  (1 = off)
    461 
    462 rtscmn:         bset    #7,d0                   * Make sure MS bit is set
    463                 move.b  d0,cfr1(a0)             * Update CFR1 image
    464                 move.b  d0,ACIA_CFR(a1)         * Send CFR to hardware
    465 *
    466 rtsexit:        rts                             * Return to caller
    467 *
    468                 .page
    469 *
    470 * wrapin -- Check input pointer for wraparound
    471 * ------    ----------------------------------
    472 wrapin:         add.w   #1,d1                   * Head index +1
    473                 cmp.w   ibufsize(a0),d1         * = buffer size ?
    474                 bcs     wrapin1                 * Jump if not
    475 *
    476                 moveq.l #0,d1                   * Wraparound
    477 *
    478 wrapin1:        rts                             * Return to caller
    479 *
    480 * wrapout -- Check output pointer for wraparound
    481 * -------    -----------------------------------
    482 wrapout:        addq.w  #1,d2                   * Tail index +1
    483                 cmp.w   obufsize(a0),d2         * = buffer size ?
    484                 bcs     wrapout1                * Jump if not
    485 *
    486                 moveq.l #0,d2                   * Wrap around if so
    487 *
    488 wrapout1:       rts                             * Return to caller
    489 *
    490                 .page
    491 *
    492 * _setsio -- setsio() -- initialize serial I/O vectors and DCD interrupts
    493 * -------    ------------------------------------------------------------
    494 _setsio:        move.w  sr,-(a7)                * Preserve status register
    495                 ori.w   #$IPL7,sr               * DISABLE INTERRUPTS
    496 *
    497                 lea     nulsiox,a0              * Get null return address
    498                 move.l  a0,_foot1               * Initialize foot1 vector
    499                 move.l  a0,_foot2               * Initialize foot2 vector
    500                 move.l  a0,_pulse1              * Initialize pulse1 vector
    501                 move.l  a0,_pulse2              * Initialize pulse2 vector
    502 *
    503                 lea     SR1ACIA,a1              * Point at Serial-1 ACIA
    504                 move.b  #$90,ACIA_IER(a1)       * Enable DCD interrupts
    505 *
    506                 lea     SR2ACIA,a1              * Point at Serial-2 ACIA
    507                 move.b  #$90,ACIA_IER(a1)       * Enable DCD interrupts
    508 *
    509                 lea     MC1ACIA,a1              * Point at MIDI-1 ACIA
    510                 move.b  #$90,ACIA_IER(a1)       * Enable DCD interrupts
    511 *
    512                 lea     MC2ACIA,a1              * Point at MIDI-2 ACIA
    513                 move.b  #$90,ACIA_IER(a1)       * Enable DCD interrupts
    514 *
    515                 lea     serintr,a0              * Initialize interrupt vector
    516                 move.l  a0,SERVECT              * ... in processor RAM
    517 *
    518                 move.w  (a7)+,sr                * RESTORE INTERRUPTS
    519 *
    520 nulsiox:        rts                             * Return to caller
    521 *
     330
     331| Handle receiver interrupt
     332
     333midrx:          move.b  ACIA_RDR(a1),d0         | Read data from ACIA
     334                move.w  ibuftl(a0),d1           | Get tail index in d1
     335                bsr     wrapin                  | Adjust for wraparound
     336                cmp.w   ibufhd(a0),d1           | Head = tail ?
     337                beq     midibf                  | If so, we drop the character
     338
     339                move.l  ibuf(a0),a2             | Get buffer address
     340                move.b  d0,0(a2,d1)             | Stash byte in buffer
     341                move.w  d1,ibuftl(a0)           | Save updated tail index
     342                bra     midtxq                  | Done  (go check tx int)
     343
     344                .page
     345
     346| Handle transmitter interrupt
     347
     348midtx:          move.w  obufhd(a0),d2           | Head index to d2
     349                cmp.w   obuftl(a0),d2           | Compare to tail index
     350                beq     midintx                 | Done if buffer empty
     351
     352                bsr     wrapout                 | Adjust pointer for wraparound
     353                move.l  obuf(a0),a2             | Get buffer base address
     354                move.b  0(a2,d2),ACIA_TDR(a1)   | Send byte on its way
     355                move.w  d2,obufhd(a0)           | Save updated head index
     356                bra     midintx                 | Done
     357
     358midibf:         move.b  d0,erbyte(a0)           | Log dropped character
     359                addq.w  #1,ibfct(a0)            | ...
     360                bra     midtxq                  | Go check Tx interrupt
     361
     362                .page
     363
     364| serput -- Output a character to a serial port
     365| ------    -----------------------------------
     366serput:         move.w  sr,-(a7)                | Save status register
     367                ori.w   #IPL7,sr                | DISABLE INTERRUPTS
     368                move.b  ACIA_ISR(a1),isr(a0)    | Get ACIA isr
     369                move.b  ACIA_CSR(a1),csr(a0)    | Get ACIA csr
     370                btst    #0,linedisc(a0)         | XON/XOFF mode ?
     371                beq     serpt_1                 | Jump if not
     372
     373                tst.b   flagxoff(a0)            | XON active ?
     374                bne     serpt_2                 | Jump if so
     375
     376serpt_1:        btst.b  #6,isr(a0)              | Is ACIA still sending ?
     377                beq     serpt_2                 | Jump if so
     378
     379                move.w  obufhd(a0),d2           | Head index to d2
     380                cmp.w   obuftl(a0),d2           | Compare to tail index
     381                bne     serpt_2                 | Jump if buffer not empty
     382
     383                move.b  d1,ACIA_TDR(a1)         | Give byte to ACIA to send
     384                bra     serpt_3                 | Go deal with RTS/CTS if needed
     385
     386serpt_2:        move.w  obuftl(a0),d2           | Tail index to d2
     387                bsr     wrapout                 | Adjust for wraparound
     388                cmp.w   obufhd(a0),d2           | Compare to head index
     389                beq     serpt_4                 | Jump if buffer full
     390
     391                move.l  obuf(a0),a2             | Get buffer base address in a2
     392                move.b  d1,0(a2,d2)             | Put character in buffer
     393                move.w  d2,obuftl(a0)           | Update buffer tail index
     394
     395serpt_3:        bsr     serchk                  | Check status on our way out
     396                bsr     rtschk                  | Handle RTS protocol
     397                move.w  (a7)+,sr                | RESTORE INTERRUPTS
     398                andi    #0xFFFE,sr              | Clear carry flag = OK
     399                rts                             | Return to caller
     400
     401serpt_4:        bsr     serchk                  | Check status on our way out
     402                bsr     rtschk                  | Handle RTS protocol
     403                move.w  (a7)+,sr                | RESTORE INTERRUPTS
     404                ori     #0x0001,sr              | Set carry flag = buffer full
     405                rts                             | Return to caller
     406
     407                .page
     408
     409| midput -- Output to MIDI
     410| ------    --------------
     411midput:         move.w  sr,-(a7)                | Save status register
     412                ori.w   #IPL7,sr                | DISABLE INTERRUPTS
     413                move.b  ACIA_ISR(a1),isr(a0)    | Get ACIA isr
     414                move.b  ACIA_CSR(a1),csr(a0)    | Get ACIA csr
     415                btst.b  #6,isr(a0)              | Is ACIA still sending ?
     416                beq     midpt_2                 | Jump if so
     417
     418                move.w  obufhd(a0),d2           | Head index to d2
     419                cmp.w   obuftl(a0),d2           | Compare to tail index
     420                bne     midpt_2                 | Jump if buffer not empty
     421
     422                move.b  d1,ACIA_TDR(a1)         | Give byte to ACIA to send
     423                bra     midpt_3                 | Go set final status and exit
     424
     425midpt_2:        move.w  obuftl(a0),d2           | Tail index to d2
     426                bsr     wrapout                 | Adjust for wraparound
     427                cmp.w   obufhd(a0),d2           | Compare to head index
     428                beq     midpt_4                 | Jump if buffer full
     429
     430                move.l  obuf(a0),a2             | Get buffer base address in a2
     431                move.b  d1,0(a2,d2)             | Put character in buffer
     432                move.w  d2,obuftl(a0)           | Update buffer tail index
     433
     434midpt_3:        bsr     midchk                  | Check status on our way out
     435                move.w  (a7)+,sr                | RESTORE INTERRUPTS
     436                andi    #0xFFFE,sr              | Clear carry flag = OK
     437                rts                             | Return to caller
     438
     439midpt_4:        bsr     midchk                  | Check status on our way out
     440                move.w  (a7)+,sr                | RESTORE INTERRUPTS
     441                ori     #0x0001,sr              | Set carry flag = buffer full
     442                rts                             | Return to caller
     443
     444                .page
     445
     446| rtschk -- Check RTS mode and turn on RTS if it's enabled
     447| ------    ----------------------------------------------
     448rtschk:         btst    #1,linedisc(a0)         | RTS/CTS mode set ?
     449                beq     rtsexit                 | Jump to exit if not
     450
     451| rtson -- Turn on RTS line
     452| -----    ----------------
     453rtson:          move.b  cfr1(a0),d0             | Pick up CFR1 image
     454                bclr    #0,d0                   | Turn on RTS line  (0 = on)
     455                bra     rtscmn                  | Join common RTS code below
     456
     457| rtsoff -- Turn off RTS line
     458| ------    -----------------
     459rtsoff:         move.b  cfr1(a0),d0             | Pick up CFR1 image
     460                bset    #0,d0                   | Turn off RTS line  (1 = off)
     461
     462rtscmn:         bset    #7,d0                   | Make sure MS bit is set
     463                move.b  d0,cfr1(a0)             | Update CFR1 image
     464                move.b  d0,ACIA_CFR(a1)         | Send CFR to hardware
     465
     466rtsexit:        rts                             | Return to caller
     467
     468                .page
     469
     470| wrapin -- Check input pointer for wraparound
     471| ------    ----------------------------------
     472wrapin:         add.w   #1,d1                   | Head index +1
     473                cmp.w   ibufsize(a0),d1         | = buffer size ?
     474                bcs     wrapin1                 | Jump if not
     475
     476                moveq.l #0,d1                   | Wraparound
     477
     478wrapin1:        rts                             | Return to caller
     479
     480| wrapout -- Check output pointer for wraparound
     481| -------    -----------------------------------
     482wrapout:        addq.w  #1,d2                   | Tail index +1
     483                cmp.w   obufsize(a0),d2         | = buffer size ?
     484                bcs     wrapout1                | Jump if not
     485
     486                moveq.l #0,d2                   | Wrap around if so
     487
     488wrapout1:       rts                             | Return to caller
     489
     490                .page
     491
     492| _setsio -- setsio() -- initialize serial I/O vectors and DCD interrupts
     493| -------    ------------------------------------------------------------
     494_setsio:        move.w  sr,-(a7)                | Preserve status register
     495                ori.w   #IPL7,sr                | DISABLE INTERRUPTS
     496
     497                lea     nulsiox,a0              | Get null return address
     498                move.l  a0,_foot1               | Initialize foot1 vector
     499                move.l  a0,_foot2               | Initialize foot2 vector
     500                move.l  a0,_pulse1              | Initialize pulse1 vector
     501                move.l  a0,_pulse2              | Initialize pulse2 vector
     502
     503                lea     SR1ACIA,a1              | Point at Serial-1 ACIA
     504                move.b  #0x90,ACIA_IER(a1)      | Enable DCD interrupts
     505
     506                lea     SR2ACIA,a1              | Point at Serial-2 ACIA
     507                move.b  #0x90,ACIA_IER(a1)      | Enable DCD interrupts
     508
     509                lea     MC1ACIA,a1              | Point at MIDI-1 ACIA
     510                move.b  #0x90,ACIA_IER(a1)      | Enable DCD interrupts
     511
     512                lea     MC2ACIA,a1              | Point at MIDI-2 ACIA
     513                move.b  #0x90,ACIA_IER(a1)      | Enable DCD interrupts
     514
     515                lea     serintr,a0              | Initialize interrupt vector
     516                move.l  a0,SERVECT              | ... in processor RAM
     517
     518                move.w  (a7)+,sr                | RESTORE INTERRUPTS
     519
     520nulsiox:        rts                             | Return to caller
     521
    522522                .bss
    523 *
    524 * DCD interrupt processor vectors
    525 * -------------------------------
    526 _foot1:         .ds.l   1                       * short (*foot1)();
    527 _foot2:         .ds.l   1                       * short (*foot2)();
    528 _pulse1:        .ds.l   1                       * short (*pulse1)();
    529 _pulse2:        .ds.l   1                       * short (*pulse2)();
    530 *
     523
     524| DCD interrupt processor vectors
     525| -------------------------------
     526_foot1:         .ds.l   1                       | short (|foot1)();
     527_foot2:         .ds.l   1                       | short (|foot2)();
     528_pulse1:        .ds.l   1                       | short (|pulse1)();
     529_pulse2:        .ds.l   1                       | short (|pulse2)();
     530
    531531                .end
Note: See TracChangeset for help on using the changeset viewer.