source: buchla-68k/ram/serintr.s@ abd4109

Last change on this file since abd4109 was 4f508e6, checked in by Thomas Lopatic <thomas@…>, 7 years ago

Converted assembly language files.

  • Property mode set to 100644
File size: 15.3 KB
Line 
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 .text
14
15 .xdef _setsio
16
17 .xdef _foot1
18 .xdef _foot2
19 .xdef _pulse1
20 .xdef _pulse2
21
22 .xdef serintr
23
24 .xdef serint
25 .xdef midint
26
27 .xdef wrapin
28 .xdef wrapout
29
30 .xdef serput
31 .xdef midput
32
33 .xdef rtschk
34
35 .xdef rtson
36 .xdef rtsoff
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
329 rts
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
522 .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
531 .end
Note: See TracBrowser for help on using the repository browser.