Changeset 4f508e6 in buchla-68k for ram/serintr.s
- Timestamp:
- 07/01/2017 02:34:46 PM (7 years ago)
- Branches:
- master
- Children:
- 08e1da1
- Parents:
- f40a309
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
ram/serintr.s
rf40a309 r4f508e6 1 *------------------------------------------------------------------------------2 *serintr.s -- MIDAS-VII serial I/O subroutines3 *Version 4 -- 1988-12-13 -- D.N. Lynx Crowe4 * 5 *These subroutines replace those in bios.s in order to add support for6 *MIDAS-VII foot pedal and pulse inputs, and pulse outputs.7 * 8 *WARNING: The code below uses addresses in the bios RAM area. These addresses9 *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 13 13 .text 14 * 14 15 15 .xdef _setsio 16 * 16 17 17 .xdef _foot1 18 18 .xdef _foot2 19 19 .xdef _pulse1 20 20 .xdef _pulse2 21 * 21 22 22 .xdef serintr 23 * 23 24 24 .xdef serint 25 25 .xdef midint 26 * 26 27 27 .xdef wrapin 28 28 .xdef wrapout 29 * 29 30 30 .xdef serput 31 31 .xdef midput 32 * 32 33 33 .xdef rtschk 34 * 34 35 35 .xdef rtson 36 36 .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 address56 * 57 IPL7 .equ $0700 *IPL 7 value for sr58 * 59 *ACIA I/O Addresses:60 *-------------------61 SR1ACIA .equ $3A8001 *Serial-1 ACIA base address62 SR2ACIA .equ $3A8009 *Serial-2 ACIA base address63 MC1ACIA .equ $3AC001 *MIDI-1 ACIA base address64 MC2ACIA .equ $3AC009 *MIDI-2 ACIA base address65 * 66 *ACIA Register offsets:67 *----------------------68 ACIA_IER .equ 0 *ACIA IER offset69 ACIA_ISR .equ 0 *ACIA ISR offset70 ACIA_CSR .equ 2 *ACIA CSR offset71 ACIA_CFR .equ 2 *ACIA CFR offset72 ACIA_TBR .equ 4 *ACIA TBR offset73 ACIA_TDR .equ 6 *ACIA TDR offset74 ACIA_RDR .equ 6 *ACIA RDR offset75 * 76 *iorec structure definitions:77 *----------------------------78 IORECLN .equ 40 *Length of an iorec structure79 * 80 ibuf .equ 0 *Input buffer base address81 ibufsize .equ 4 *Input buffer size (bytes)82 ibufhd .equ 6 *Input buffer head index83 ibuftl .equ 8 *Input buffer tail index84 ibuflow .equ 10 *Input buffer low water mark85 ibufhi .equ 12 *Input buffer high water mark86 obuf .equ 14 *Output buffer base address87 obufsize .equ 18 *Output buffer size (bytes)88 obufhd .equ 20 *Output buffer head index89 obuftl .equ 22 *Output buffer tail index90 obuflow .equ 24 *Output buffer low water mark91 obufhi .equ 26 *Output buffer high water mark92 cfr0 .equ 28 *ACIA CFR, MS bit = 093 cfr1 .equ 29 *ACIA CFR, MS bit = 194 flagxon .equ 30 *XON flag (non-zero = XOFF sent)95 flagxoff .equ 31 *XOFF flag (non-zero = active)96 linedisc .equ 32 *Line discipline flags97 erbyte .equ 33 *Last error byte98 isr .equ 34 *ACIA ISR on interrupt99 csr .equ 35 *ACIA CSR on interrupt100 errct .equ 36 *Error count (FRM/OVR/BRK)101 ibfct .equ 38 *Input buffer full count102 * 103 .page 104 * 105 *serintr -- Serial (Serial-1, Serial-2, MIDI-1, MIDI-2) interrupt handler106 *------- -------------------------------------------------------------107 serintr: movem.l d0-d3/a0-a2,-(a7) *Save registers108 lea SR1IOREC,a0 *Point at Serial-1 iorec109 lea SR1ACIA,a1 *Point at Serial-1 ACIA110 movea.l _foot1,a2 *Point at foot sw. 1 processor111 bsr serint *Go process (possible) int.112 * 113 lea SR2IOREC,a0 *Point at Serial-2 iorec114 lea SR2ACIA,a1 *Point at Serial-2 ACIA115 movea.l _foot2,a2 *Point at foot sw. 2 processor116 bsr serint *Go process (possible) int.117 * 118 lea MC1IOREC,a0 *Point at MIDI-1 iorec119 lea MC1ACIA,a1 *Point at MIDI-1 ACIA120 movea.l _pulse1,a2 *Point at pulse 1 processor121 bsr midint *Go process (possible) int.122 * 123 lea MC2IOREC,a0 *Point at MIDI-2 iorec124 lea MC2ACIA,a1 *Point at MIDI-2 ACIA125 movea.l _pulse2,a2 *Point at pulse 2 processor126 bsr midint *Go process (possible) int.127 * 128 movem.l (a7)+,d0-d3/a0-a2 *Restore registers129 rte *Return from exception130 * 131 .page 132 * 133 *serint -- Process an interrupt from Serial-1 or Serial-2134 *------ ----------------------------------------------135 serint: move.b ACIA_ISR(a1),isr(a0) *Get and save ISR136 move.b ACIA_CSR(a1),csr(a0) *Get and save CSR137 * 138 btst.b #7,isr(a0) *Was int for this device ?139 beq serintx *Jump if not140 * 141 serchk: btst.b #1,isr(a0) *FRM/OVR/BRK error ?142 bne sererr *Jump if so143 * 144 btst.b #0,isr(a0) *Receiver interrupt ?145 bne serrx *Jump if so146 * 147 sertxq: btst.b #6,isr(a0) *Transmitter interrupt ?148 bne sertx *Jump if so149 * 150 serctq: btst.b #5,isr(a0) *CTS interrupt ?151 bne sercts *Jump if so152 * 153 serintx: btst.b #4,isr(a0) *DCD interrupt ?154 bne calldcd *Jump if so155 * 156 serdone: rts *Return to caller157 * 158 calldcd: move.b csr(a0),d0 *Get CSR interrupt status159 btst.l #4,d0 *Check DCD input (0 = active)160 bne calldcd0 *Jump if line was inactive161 * 162 moveq.l #1,d0 *Set footswitch status to TRUE163 bra calldcd1 *...164 * 165 calldcd0: moveq.l #0,d0 *Set footswitch status to FALSE166 * 167 calldcd1: move.w d0,-(a7) *Call the footswitch processor168 jsr (a2) * ... (*footX)(status)169 tst.w (a7)+ *...170 rts *Return to caller171 * 172 .page 173 * 174 *Handle serial I/O port error175 * 176 sererr: addq.w #1,errct(a0) *Update error count177 move.b ACIA_RDR(a1),erbyte(a0) *Get error byte178 rts *Return to caller179 * 180 * 181 *Handle CTS interupt182 * 183 sercts: btst.b #1,linedisc(a0) *RTS/CTS mode ?184 beq serintx *Ignore if not185 * 186 btst.b #5,csr(a0) *CTS set ?187 beq serintx *Ignore if not188 * 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 d2193 cmp.w obuftl(a0),d2 *Compare to tail index194 beq serintx *Done if buffer empty195 * 196 bsr wrapout *Adjust pointer for wraparound197 move.l obuf(a0),a2 *Get buffer base in a2198 move.b 0(a2,d2),ACIA_TDR(a1) *Send byte on its way199 move.w d2,obufhd(a0) *Save updated head index200 bra serintx *Done201 * 202 .page 203 * 204 *Handle receiver interrupt205 * 206 serrx: btst.b #1,linedisc(a0) *RTS/CTS mode set ?207 beq serrx1 *Jump if not208 * 209 bsr rtsoff *Turn off RTS210 * 211 serrx1: move.b ACIA_RDR(a1),d0 *Read data from ACIA212 btst.b #1,linedisc(a0) *RTS/CTS mode set ?213 bne serrx3 *Jump if so214 * 215 btst.b #0,linedisc(a0) *XON/XOFF mode set ?216 beq serrx3 *Jump if not217 * 218 cmpi.b # $11,d0 *Is this an XON ?219 bne serrx2 *Jump if not220 * 221 move.b # $00,flagxoff(a0) *Clear flagxoff222 bra sertxq *Done223 * 224 serrx2: cmpi.b # $13,d0 *Is this an XOFF ?225 bne serrx3 *Jump if not226 * 227 move.b # $FF,flagxoff(a0) *Set flagxoff228 bra sertxq *Done229 * 230 serrx3: move.w ibuftl(a0),d1 *Get tail index in d1231 bsr wrapin *Adjust for wraparound232 cmp.w ibufhd(a0),d1 *Head = tail ?233 beq seribf *If so, we drop the character234 * 235 .page 236 move.l ibuf(a0),a2 *Get buffer address237 move.b d0,0(a2,d1) *Stash byte in buffer238 move.w d1,ibuftl(a0) *Save updated tail index239 move.w ibuftl(a0),d2 *Tail index to d2240 move.w ibufhd(a0),d3 *Head index to d3241 cmp.w d3,d2 *Head > Tail ?242 bhi rsi_1 *Jump if not243 * 244 add.w ibufsize(a0),d2 *Add buffer size to tail index245 * 246 rsi_1: sub.w d3,d2 *Length = (adjusted)Tail - Head247 cmp.w ibufhi(a0),d2 *Hit high water mark ?248 bne serrx4 *Jump if not249 * 250 btst.b #1,linedisc(a0) *RTS/CTS mode set ?251 bne sertxq *Done if so252 * 253 btst.b #0,linedisc(a0) *XON/XOFF mode set ?254 beq serrx4 *Jump if not255 * 256 tst.b flagxon(a0) *XOFF already sent ?257 bne serrx4 *Jump if so258 * 259 move.b # $FF,flagxon(a0) *Set the flag260 move.b # $13,d1 *Send an XOFF261 bsr serput *...262 * 263 serrx4: btst #1,linedisc(a0) *RTS/CTS mode set ?264 beq sertxq *Done if not265 * 266 bsr rtson *Turn on RTS267 bra sertxq *Done268 * 269 .page 270 * 271 *Handle transmitter interrupt272 * 273 sertx: btst.b #1,linedisc(a0) *RTS/CTS mode set ?274 bne sertx2 *If so, go check CTS275 * 276 btst.b #0,linedisc(a0) *XON/XOFF mode set ?277 beq sertx1 *Jump if not278 * 279 tst.b flagxoff(a0) *Check flagxoff280 bne serctq *Done if set281 * 282 sertx1: move.w obufhd(a0),d2 *Head index to d2283 cmp.w obuftl(a0),d2 *Compare to tail index284 beq serctq *Done if buffer empty285 * 286 bsr wrapout *Adjust pointer for wraparound287 move.l obuf(a0),a2 *Get buffer base address288 move.b 0(a2,d2),ACIA_TDR(a1) *Send byte on its way289 move.w d2,obufhd(a0) *Save updated head index290 bra serctq *Done291 * 292 sertx2: btst.b #5,csr(a0) *CTS set in csr ?293 beq serctq *If not, go check for CTS int294 * 295 bra sertx1 *CTS was set, go transmit296 * 297 seribf: move.b d0,erbyte(a0) *Log dropped character298 addq.w #1,ibfct(a0) *...299 bra sertxq *Go check Tx interrupt300 * 301 .page 302 * 303 *midint -- Process an interrupt from MIDI-1 or MIDI-2304 *------ ------------------------------------------305 midint: move.b ACIA_ISR(a1),isr(a0) *Get and save ISR306 move.b ACIA_CSR(a1),csr(a0) *Get and save CSR307 * 308 btst.b #7,isr(a0) *Was int for this device ?309 beq midintx *Jump if not310 * 311 midchk: btst.b #1,isr(a0) *FRM/OVR/BRK error ?312 bne miderr *Jump if so313 * 314 btst.b #0,isr(a0) *Receiver interrupt ?315 bne midrx *Jump if so316 * 317 midtxq: btst.b #6,isr(a0) *Transmitter interrupt ?318 bne midtx *Jump if so319 * 320 midintx: btst #4,isr(a0) *DCD interrupt ?321 bne mididcd *Jump if so322 * 323 mididone: rts *Return to caller324 * 325 mididcd: jmp (a2) *Exit through the DCD processor326 * 327 miderr: addq.w #1,errct(a0) *Update error count328 move.b ACIA_RDR(a1),erbyte(a0) *Get error byte37 38 | ============================================================================== 39 40 | The following addresses, marked by <==, are bios version dependent: 41 42 RAM = 0x00000400 | Beginning of system RAM area <== 43 44 SR1IOREC = RAM+0x0AB0 | Serial-1 iorec structure <== 45 SR2IOREC = RAM+0x0AD8 | Serial-2 iorec structure <== 46 MC1IOREC = RAM+0x0B00 | MIDI-1 iorec structure <== 47 MC2IOREC = RAM+0x0B28 | MIDI-2 iorec structure <== 48 49 | End of bios version dependent addresses. 50 51 | ============================================================================== 52 53 .page 54 55 SERVECT = 0x000074 | Level 5 interrupt autovector address 56 57 IPL7 = 0x0700 | IPL 7 value for sr 58 59 | ACIA I/O Addresses: 60 | ------------------- 61 SR1ACIA = 0x3A8001 | Serial-1 ACIA base address 62 SR2ACIA = 0x3A8009 | Serial-2 ACIA base address 63 MC1ACIA = 0x3AC001 | MIDI-1 ACIA base address 64 MC2ACIA = 0x3AC009 | MIDI-2 ACIA base address 65 66 | ACIA Register offsets: 67 | ---------------------- 68 ACIA_IER = 0 | ACIA IER offset 69 ACIA_ISR = 0 | ACIA ISR offset 70 ACIA_CSR = 2 | ACIA CSR offset 71 ACIA_CFR = 2 | ACIA CFR offset 72 ACIA_TBR = 4 | ACIA TBR offset 73 ACIA_TDR = 6 | ACIA TDR offset 74 ACIA_RDR = 6 | ACIA RDR offset 75 76 | iorec structure definitions: 77 | ---------------------------- 78 IORECLN = 40 | Length of an iorec structure 79 80 ibuf = 0 | Input buffer base address 81 ibufsize = 4 | Input buffer size (bytes) 82 ibufhd = 6 | Input buffer head index 83 ibuftl = 8 | Input buffer tail index 84 ibuflow = 10 | Input buffer low water mark 85 ibufhi = 12 | Input buffer high water mark 86 obuf = 14 | Output buffer base address 87 obufsize = 18 | Output buffer size (bytes) 88 obufhd = 20 | Output buffer head index 89 obuftl = 22 | Output buffer tail index 90 obuflow = 24 | Output buffer low water mark 91 obufhi = 26 | Output buffer high water mark 92 cfr0 = 28 | ACIA CFR, MS bit = 0 93 cfr1 = 29 | ACIA CFR, MS bit = 1 94 flagxon = 30 | XON flag (non-zero = XOFF sent) 95 flagxoff = 31 | XOFF flag (non-zero = active) 96 linedisc = 32 | Line discipline flags 97 erbyte = 33 | Last error byte 98 isr = 34 | ACIA ISR on interrupt 99 csr = 35 | ACIA CSR on interrupt 100 errct = 36 | Error count (FRM/OVR/BRK) 101 ibfct = 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 #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 224 serrx2: 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 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 #0xFF,flagxon(a0) | Set the flag 260 move.b #0x13,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 329 329 rts 330 * 331 *Handle receiver interrupt332 * 333 midrx: move.b ACIA_RDR(a1),d0 *Read data from ACIA334 move.w ibuftl(a0),d1 *Get tail index in d1335 bsr wrapin *Adjust for wraparound336 cmp.w ibufhd(a0),d1 *Head = tail ?337 beq midibf *If so, we drop the character338 * 339 move.l ibuf(a0),a2 *Get buffer address340 move.b d0,0(a2,d1) *Stash byte in buffer341 move.w d1,ibuftl(a0) *Save updated tail index342 bra midtxq *Done (go check tx int)343 * 344 .page 345 * 346 *Handle transmitter interrupt347 * 348 midtx: move.w obufhd(a0),d2 *Head index to d2349 cmp.w obuftl(a0),d2 *Compare to tail index350 beq midintx *Done if buffer empty351 * 352 bsr wrapout *Adjust pointer for wraparound353 move.l obuf(a0),a2 *Get buffer base address354 move.b 0(a2,d2),ACIA_TDR(a1) *Send byte on its way355 move.w d2,obufhd(a0) *Save updated head index356 bra midintx *Done357 * 358 midibf: move.b d0,erbyte(a0) *Log dropped character359 addq.w #1,ibfct(a0) *...360 bra midtxq *Go check Tx interrupt361 * 362 .page 363 * 364 *serput -- Output a character to a serial port365 *------ -----------------------------------366 serput: move.w sr,-(a7) *Save status register367 ori.w #IPL7,sr *DISABLE INTERRUPTS368 move.b ACIA_ISR(a1),isr(a0) *Get ACIA isr369 move.b ACIA_CSR(a1),csr(a0) *Get ACIA csr370 btst #0,linedisc(a0) *XON/XOFF mode ?371 beq serpt_1 *Jump if not372 * 373 tst.b flagxoff(a0) *XON active ?374 bne serpt_2 *Jump if so375 * 376 serpt_1: btst.b #6,isr(a0) *Is ACIA still sending ?377 beq serpt_2 *Jump if so378 * 379 move.w obufhd(a0),d2 *Head index to d2380 cmp.w obuftl(a0),d2 *Compare to tail index381 bne serpt_2 *Jump if buffer not empty382 * 383 move.b d1,ACIA_TDR(a1) *Give byte to ACIA to send384 bra serpt_3 *Go deal with RTS/CTS if needed385 * 386 serpt_2: move.w obuftl(a0),d2 *Tail index to d2387 bsr wrapout *Adjust for wraparound388 cmp.w obufhd(a0),d2 *Compare to head index389 beq serpt_4 *Jump if buffer full390 * 391 move.l obuf(a0),a2 *Get buffer base address in a2392 move.b d1,0(a2,d2) *Put character in buffer393 move.w d2,obuftl(a0) *Update buffer tail index394 * 395 serpt_3: bsr serchk *Check status on our way out396 bsr rtschk *Handle RTS protocol397 move.w (a7)+,sr *RESTORE INTERRUPTS398 andi # $FFFE,sr *Clear carry flag = OK399 rts *Return to caller400 * 401 serpt_4: bsr serchk *Check status on our way out402 bsr rtschk *Handle RTS protocol403 move.w (a7)+,sr *RESTORE INTERRUPTS404 ori # $0001,sr *Set carry flag = buffer full405 rts *Return to caller406 * 407 .page 408 * 409 *midput -- Output to MIDI410 *------ --------------411 midput: move.w sr,-(a7) *Save status register412 ori.w #IPL7,sr *DISABLE INTERRUPTS413 move.b ACIA_ISR(a1),isr(a0) *Get ACIA isr414 move.b ACIA_CSR(a1),csr(a0) *Get ACIA csr415 btst.b #6,isr(a0) *Is ACIA still sending ?416 beq midpt_2 *Jump if so417 * 418 move.w obufhd(a0),d2 *Head index to d2419 cmp.w obuftl(a0),d2 *Compare to tail index420 bne midpt_2 *Jump if buffer not empty421 * 422 move.b d1,ACIA_TDR(a1) *Give byte to ACIA to send423 bra midpt_3 *Go set final status and exit424 * 425 midpt_2: move.w obuftl(a0),d2 *Tail index to d2426 bsr wrapout *Adjust for wraparound427 cmp.w obufhd(a0),d2 *Compare to head index428 beq midpt_4 *Jump if buffer full429 * 430 move.l obuf(a0),a2 *Get buffer base address in a2431 move.b d1,0(a2,d2) *Put character in buffer432 move.w d2,obuftl(a0) *Update buffer tail index433 * 434 midpt_3: bsr midchk *Check status on our way out435 move.w (a7)+,sr *RESTORE INTERRUPTS436 andi # $FFFE,sr *Clear carry flag = OK437 rts *Return to caller438 * 439 midpt_4: bsr midchk *Check status on our way out440 move.w (a7)+,sr *RESTORE INTERRUPTS441 ori # $0001,sr *Set carry flag = buffer full442 rts *Return to caller443 * 444 .page 445 * 446 *rtschk -- Check RTS mode and turn on RTS if it's enabled447 *------ ----------------------------------------------448 rtschk: btst #1,linedisc(a0) *RTS/CTS mode set ?449 beq rtsexit *Jump to exit if not450 * 451 *rtson -- Turn on RTS line452 *----- ----------------453 rtson: move.b cfr1(a0),d0 *Pick up CFR1 image454 bclr #0,d0 *Turn on RTS line (0 = on)455 bra rtscmn *Join common RTS code below456 * 457 *rtsoff -- Turn off RTS line458 *------ -----------------459 rtsoff: move.b cfr1(a0),d0 *Pick up CFR1 image460 bset #0,d0 *Turn off RTS line (1 = off)461 462 rtscmn: bset #7,d0 *Make sure MS bit is set463 move.b d0,cfr1(a0) *Update CFR1 image464 move.b d0,ACIA_CFR(a1) *Send CFR to hardware465 * 466 rtsexit: rts *Return to caller467 * 468 .page 469 * 470 *wrapin -- Check input pointer for wraparound471 *------ ----------------------------------472 wrapin: add.w #1,d1 *Head index +1473 cmp.w ibufsize(a0),d1 *= buffer size ?474 bcs wrapin1 *Jump if not475 * 476 moveq.l #0,d1 *Wraparound477 * 478 wrapin1: rts *Return to caller479 * 480 *wrapout -- Check output pointer for wraparound481 *------- -----------------------------------482 wrapout: addq.w #1,d2 *Tail index +1483 cmp.w obufsize(a0),d2 *= buffer size ?484 bcs wrapout1 *Jump if not485 * 486 moveq.l #0,d2 *Wrap around if so487 * 488 wrapout1: rts *Return to caller489 * 490 .page 491 * 492 *_setsio -- setsio() -- initialize serial I/O vectors and DCD interrupts493 *------- ------------------------------------------------------------494 _setsio: move.w sr,-(a7) *Preserve status register495 ori.w # $IPL7,sr *DISABLE INTERRUPTS496 * 497 lea nulsiox,a0 *Get null return address498 move.l a0,_foot1 *Initialize foot1 vector499 move.l a0,_foot2 *Initialize foot2 vector500 move.l a0,_pulse1 *Initialize pulse1 vector501 move.l a0,_pulse2 *Initialize pulse2 vector502 * 503 lea SR1ACIA,a1 *Point at Serial-1 ACIA504 move.b # $90,ACIA_IER(a1) *Enable DCD interrupts505 * 506 lea SR2ACIA,a1 *Point at Serial-2 ACIA507 move.b # $90,ACIA_IER(a1) *Enable DCD interrupts508 * 509 lea MC1ACIA,a1 *Point at MIDI-1 ACIA510 move.b # $90,ACIA_IER(a1) *Enable DCD interrupts511 * 512 lea MC2ACIA,a1 *Point at MIDI-2 ACIA513 move.b # $90,ACIA_IER(a1) *Enable DCD interrupts514 * 515 lea serintr,a0 *Initialize interrupt vector516 move.l a0,SERVECT *... in processor RAM517 * 518 move.w (a7)+,sr *RESTORE INTERRUPTS519 * 520 nulsiox: rts *Return to caller521 * 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 #0xFFFE,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 #0x0001,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 #0xFFFE,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 #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 | ------ ---------------------------------------------- 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 #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 520 nulsiox: rts | Return to caller 521 522 522 .bss 523 * 524 *DCD interrupt processor vectors525 *-------------------------------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 531 531 .end
Note:
See TracChangeset
for help on using the changeset viewer.