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

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

Added RAM files.

  • Property mode set to 100644
File size: 16.1 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 .equ $00000400 * Beginning of system RAM area <==
43*
44SR1IOREC .equ RAM+$0AB0 * Serial-1 iorec structure <==
45SR2IOREC .equ RAM+$0AD8 * Serial-2 iorec structure <==
46MC1IOREC .equ RAM+$0B00 * MIDI-1 iorec structure <==
47MC2IOREC .equ RAM+$0B28 * MIDI-2 iorec structure <==
48*
49* End of bios version dependent addresses.
50*
51* ==============================================================================
52*
53 .page
54*
55SERVECT .equ $000074 * Level 5 interrupt autovector address
56*
57IPL7 .equ $0700 * IPL 7 value for sr
58*
59* ACIA I/O Addresses:
60* -------------------
61SR1ACIA .equ $3A8001 * Serial-1 ACIA base address
62SR2ACIA .equ $3A8009 * Serial-2 ACIA base address
63MC1ACIA .equ $3AC001 * MIDI-1 ACIA base address
64MC2ACIA .equ $3AC009 * MIDI-2 ACIA base address
65*
66* ACIA Register offsets:
67* ----------------------
68ACIA_IER .equ 0 * ACIA IER offset
69ACIA_ISR .equ 0 * ACIA ISR offset
70ACIA_CSR .equ 2 * ACIA CSR offset
71ACIA_CFR .equ 2 * ACIA CFR offset
72ACIA_TBR .equ 4 * ACIA TBR offset
73ACIA_TDR .equ 6 * ACIA TDR offset
74ACIA_RDR .equ 6 * ACIA RDR offset
75*
76* iorec structure definitions:
77* ----------------------------
78IORECLN .equ 40 * Length of an iorec structure
79*
80ibuf .equ 0 * Input buffer base address
81ibufsize .equ 4 * Input buffer size (bytes)
82ibufhd .equ 6 * Input buffer head index
83ibuftl .equ 8 * Input buffer tail index
84ibuflow .equ 10 * Input buffer low water mark
85ibufhi .equ 12 * Input buffer high water mark
86obuf .equ 14 * Output buffer base address
87obufsize .equ 18 * Output buffer size (bytes)
88obufhd .equ 20 * Output buffer head index
89obuftl .equ 22 * Output buffer tail index
90obuflow .equ 24 * Output buffer low water mark
91obufhi .equ 26 * Output buffer high water mark
92cfr0 .equ 28 * ACIA CFR, MS bit = 0
93cfr1 .equ 29 * ACIA CFR, MS bit = 1
94flagxon .equ 30 * XON flag (non-zero = XOFF sent)
95flagxoff .equ 31 * XOFF flag (non-zero = active)
96linedisc .equ 32 * Line discipline flags
97erbyte .equ 33 * Last error byte
98isr .equ 34 * ACIA ISR on interrupt
99csr .equ 35 * ACIA CSR on interrupt
100errct .equ 36 * Error count (FRM/OVR/BRK)
101ibfct .equ 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 #$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*
224serrx2: 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*
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 #$FF,flagxon(a0) * Set the flag
260 move.b #$13,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 #$FFFE,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 #$0001,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 #$FFFE,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 #$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* ------ ----------------------------------------------
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 #$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*
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.