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
RevLine 
[4f508e6]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
[f40a309]13 .text
[4f508e6]14
[f40a309]15 .xdef _setsio
[4f508e6]16
[f40a309]17 .xdef _foot1
18 .xdef _foot2
19 .xdef _pulse1
20 .xdef _pulse2
[4f508e6]21
[f40a309]22 .xdef serintr
[4f508e6]23
[f40a309]24 .xdef serint
25 .xdef midint
[4f508e6]26
[f40a309]27 .xdef wrapin
28 .xdef wrapout
[4f508e6]29
[f40a309]30 .xdef serput
31 .xdef midput
[4f508e6]32
[f40a309]33 .xdef rtschk
[4f508e6]34
[f40a309]35 .xdef rtson
36 .xdef rtsoff
[4f508e6]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
[f40a309]53 .page
[4f508e6]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
[f40a309]103 .page
[4f508e6]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
[f40a309]131 .page
[4f508e6]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
[f40a309]172 .page
[4f508e6]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
[f40a309]202 .page
[4f508e6]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
[f40a309]235 .page
[4f508e6]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
[f40a309]269 .page
[4f508e6]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
[f40a309]301 .page
[4f508e6]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
[f40a309]329 rts
[4f508e6]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
[f40a309]344 .page
[4f508e6]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
[f40a309]362 .page
[4f508e6]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
[f40a309]407 .page
[4f508e6]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
[f40a309]444 .page
[4f508e6]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
[f40a309]468 .page
[4f508e6]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
[f40a309]490 .page
[4f508e6]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
[f40a309]522 .bss
[4f508e6]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
[f40a309]531 .end
Note: See TracBrowser for help on using the repository browser.