;----------------------------------------------------------------------------
;File name:	MIDI_SER.S			Revision date:	1999.12.29
;Creator:	Ulf Ronald Andersson		Creation date:	1999.12.29
;(c)1999 by:	Ulf Ronald Andersson		All rights reserved
;Feedback to:	dlanor@oden.se
;----------------------------------------------------------------------------
	include	RA_SYS.I
;----------------------------------------------------------------------------
	TEXT
;----------------------------------------------------------------------------
start:
	bra.w	init_1
;----------------------------------------------------------------------------
Kbdvbase_ikbd_vec_p:
	dc.l	$00000020
;----------------------------------------------------------------------------
;Start of:	Interrupt driven MIDI interface code
;----------------------------------------------------------------------------
	dc.l	'XBRA'
	dc.l	'MIRS'
ol_iv_M1_kb_midi_p:
	dc.l	0
nu_iv_M1_kb_midi:
	move.b	hw_MIDI_cont.w,-(sp)
	bpl.w	nu_iv_M1_kb_midi_ikbd
	btst	#$00,(sp)
	movem.l	d0-d1/a0,-(sp)
	beq.w	try_transmission
	move.b	hw_MIDI_data.w,d0		;receive data
	lea	MIDI_IOREC(pc),a0
	moveq	#$70,d1
	and.b	$000C(sp),d1
	bne.w	L00180
	tst.b	Io_flow_ctr(a0)
	beq.s	Receive_unshaken
	cmpi.b	#$11,d0
	beq.s	.received_Xon
	cmpi.b	#$13,d0
	beq.s	.received_Xoff
	move	Rx_tail_ix(a0),d1
	addq	#1,d1
	cmp	Rx_size_ix(a0),d1
	bcs.s	.Rx_tail_adjusted
	moveq	#$00,d1
.Rx_tail_adjusted:
	cmp	Rx_head_ix(a0),d1
	beq.s	Receive_data_done
	move	d1,Rx_tail_ix(a0)
	movea.l	Rx_buffer_p(a0),a0
	move.b	d0,$00(a0,d1.l)
	lea	MIDI_IOREC(pc),a0
	sub	Rx_head_ix(a0),d1
	bcc.s	.Rx_size_adjusted
	add	Rx_size_ix(a0),d1
.Rx_size_adjusted:
	cmp	Rx_hi_fill(a0),d1
	bcs.s	Receive_data_done
	bset	#$07,Rx_locked_f(a0)
	bne.s	Receive_data_done
	move.b	#$13,Tx_softnext(a0)
	bra.s	.L000A4
;-------
.received_Xon:
	clr.b	Tx_locked_f(a0)
.L000A4:
	ori.b	#$20,Io_shadow_1(a0)
	move.b	Io_shadow_1(a0),hw_MIDI_cont.w
	bra.s	Receive_data_done
;-------
.received_Xoff:
	st	Tx_locked_f(a0)
	bra.s	Receive_data_done
;-------
Receive_unshaken:
	lea	MIDI_IOREC(pc),a0
	move	Rx_tail_ix(a0),d1
	addq	#1,d1
	cmp	Rx_size_ix(a0),d1
	bcs.s	.Rx_tail_adjusted
	moveq	#$00,d1
.Rx_tail_adjusted:
	cmp	Rx_head_ix(a0),d1
	beq.s	Receive_data_done
	move	d1,Rx_tail_ix(a0)
	movea.l	Rx_buffer_p(a0),a0
	move.b	d0,$00(a0,d1.l)
Receive_data_done:
	btst	#$05,MIDI_Io_shadow_1.l
	beq.s	rts_or_mfp_I4_midi
try_transmission:
	btst	#$01,hw_MIDI_cont.w
	beq.s	rts_or_mfp_I4_midi
	moveq	#$00,d1
	lea	MIDI_IOREC(pc),a0
	tst.b	Io_flow_ctr(a0)
	beq.s	L0010E
	move.b	Tx_softnext(a0),d0		;any old data to send ?
	beq.s	L00108
	move.b	d1,Tx_softnext(a0)		;mark Tx_softnext as empty
	move.b	d0,hw_MIDI_data.w		;transmit old data
	bra.s	rts_or_mfp_I4_midi
;-------
L00108:
	tst.b	Tx_locked_f(a0)
	bne.s	L00118
L0010E:
	move	Tx_head_ix(a0),d1
	cmp	Tx_tail_ix(a0),d1
	bne.s	L00126
L00118:
	andi.b	#$9F,Io_shadow_1(a0)
	move.b	Io_shadow_1(a0),hw_MIDI_cont.w
	bra.s	rts_or_mfp_I4_midi
;-------
L00126:
	addq	#1,d1
	cmp	Tx_size_ix(a0),d1
	bcs.s	L00130
	moveq	#$00,d1
L00130:
	move	d1,Tx_head_ix(a0)
	movea.l	Tx_buffer_p(a0),a0
	move.b	$00(a0,d1.l),hw_MIDI_data.w	;transmit new data
rts_or_mfp_I4_midi:
	movem.l	(sp)+,d0-d1/a0
	addq.l	#2,sp
	btst	#$04,hw_M1_gpip.w
	beq.w	nu_iv_M1_kb_midi
	move.b	#$BF,hw_M1_isrb.w
	rte
;----------------------------------------------------------------------------
nu_iv_M1_kb_midi_ikbd:
	addq.l	#2,sp
	movem.l	d0-d3/a0-a3/a5,-(sp)
	lea	$0000.w,a5
	movea.l	Kbdvbase_ikbd_vec_p.l,a2	; a2 -> ikbd_vec
	movea.l	(a2),a2				; a2 -> ikbd_vec code
	jsr	(a2)				; call ikbd_vec code
	movem.l	(sp)+,d0-d3/a0-a3/a5
	btst	#$04,hw_M1_gpip.w
	beq.w	nu_iv_M1_kb_midi
	move.b	#$BF,hw_M1_isrb.w
	rte

L00180:
	or.b	d1,Io_shadow_0(a0)
	bra.w	try_transmission
;----------------------------------------------------------------------------
;End of:	Interrupt driven MIDI interface code
;----------------------------------------------------------------------------
;Start of:	MAPTAB functions
;----------------------------------------------------------------------------
MIDI_Bconout:
	lea	$0006(sp),a0
	move	(a0),d0
	lea	MIDI_IOREC.l,a0
	moveq	#$00,d1
	move	Tx_tail_ix(a0),d1
	move	Tx_size_ix(a0),d2
	addq	#1,d1
	cmp	d2,d1
	bcs.s	L001A6
	moveq	#$00,d1
L001A6:
	movea.l	Tx_buffer_p(a0),a1
	move.b	d0,$00(a1,d1.l)
	move	d1,Tx_tail_ix(a0)
	ori.b	#$20,Io_shadow_1(a0)
	move.b	Io_shadow_1(a0),hw_MIDI_cont.w
L001BE:
	move	Tx_head_ix(a0),d1
	sub	Tx_tail_ix(a0),d1
	bhi.s	L001CA
	add	d2,d1
L001CA:
	subq	#1,d1
	beq.s	L001BE
	rts
;----------------------------------------------------------------------------
MIDI_Bcostat:
	move	MIDI_Tx_head_ix.l,d1
	sub	MIDI_Tx_tail_ix.l,d1
	bhi.s	L001E4
	add	MIDI_Tx_size_ix.l,d1
L001E4:
	subq	#3,d1
	scc	d0
	ext	d0
	ext.l	d0
	rts
;----------------------------------------------------------------------------
MIDI_Bconin:
	lea	MIDI_IOREC.l,a0
	moveq	#$00,d1
	moveq	#$00,d0
	move	Rx_head_ix(a0),d1			; d1 = io_head_ix
.wait_for_char_loop:
	cmp	Rx_tail_ix(a0),d1			; d1 != io_tail_ix ?
	beq.s	.wait_for_char_loop		; else loop
	addq	#1,d1				; d1 += 1
	cmp	Rx_size_ix(a0),d1			; d1 >= io_size_ix ?
	bcs.s	.have_index			; else keep as it is
	moveq	#$00,d1
.have_index:
	movea.l	Rx_buffer_p(a0),a1		; a1 = io_buffer_p
	move.b	$00(a1,d1.l),d0			; d0 = indexed char
	move	d1,Rx_head_ix(a0)			; io_head_ix = d1
	tst.b	Io_flow_ctr(a0)
	beq.s	L00264
	tst.b	Rx_locked_f(a0)
	beq.s	L00264
	move	Rx_tail_ix(a0),d1			; d1 = io_tail_ix
	sub	Rx_head_ix(a0),d1			; d1 -= io_tail_ix
	bcc.s	.done_wrap_size
	add	Rx_size_ix(a0),d1			; d1 += io_size_ix
.done_wrap_size:
	cmp	Rx_lo_fill(a0),d1		; d1 <= io_lo_fill ?
	bhi.s	L00264				; else exit
	sf	Rx_locked_f(a0)
	move	sr,d2
	ori	#$0700,sr
	btst	#$01,Io_flow_ctr(a0)		;RTS/CTS ?
	beq.s	L0024C
	move	d2,sr
	rts
;-------
L0024C:
	moveq	#$11,d1
	btst	#$01,hw_MIDI_cont.w
	beq.s	L0025E
	move.b	d1,hw_MIDI_data.w
	move	d2,sr
	rts
;-------
L0025E:
	move	d2,sr
	move.b	d1,Tx_softnext(a0)
L00264:
	rts
;----------------------------------------------------------------------------
MIDI_Bconstat:
	move	MIDI_Rx_head_ix.l,d1
	cmp	MIDI_Rx_tail_ix.l,d1
	sne	d0
	ext	d0
	ext.l	d0
	rts
;----------------------------------------------------------------------------
MIDI_Rsconf:
	cmpi	#-$012C,$0004(sp)		; baud code = -300 ?
	bne.s	L002B2
	move.l	MIDI_Io_baudrate.l,d0
	move.l	$0006(sp),d1
	bmi.w	L003EA
	move.l	d1,d0
	bsr.w	L003EC
	tst.l	d0
	bmi.w	L003EA
	move.l	MIDI_Io_baudrate.l,d2
	move.l	d0,MIDI_Io_baudrate.l
	move.l	d2,d0
	bsr.w	L00412
	bra.w	L003EA

L002B2:
	moveq	#$00,d0
	cmpi	#-$0002,$0004(sp)		; baud code = -2 ?
	bne.s	L002C4
	move.b	MIDI_Io_baudcode.l,d0
	rts

L002C4:
	moveq	#$1C,d0
	and.b	MIDI_Io_shadow_1.l,d0
	lsr	#2,d0
	lea	X00436.l,a0
	move.b	$00(a0,d0),d0
	lsl	#8,d0
	swap	d0
	btst	#$06,MIDI_Io_shadow_1.l
	beq.s	L002F4
	btst	#$05,MIDI_Io_shadow_1.l
	beq.s	L002F4
	bset	#$0B,d0
L002F4:
	move	$0004(sp),d1			;d1 = baud code
	move.l	#31250/4,d2
	cmpi	#$0001,d1
	bhi.s	L00316
	beq.s	L0030C
	move.l	#31250,d2
L0030C:
	move.l	d2,MIDI_Io_baudrate.l
	bsr.w	L00412
L00316:
	move	$0008(sp),d2			;d2 = code for parity & stops
	bmi.s	L00356
	bset	#$07,d2
	bclr	#$00,d2
	moveq	#$07,d1
	lea	X00436.l,a0
L0032C:
	cmp.b	$00(a0,d1),d2
	dbeq	d1,L0032C
	beq.s	L00338
	moveq	#$05,d1
L00338:
	lsl.b	#2,d1
	moveq	#-$1D,d2
	move	sr,-(sp)
	ori	#$0700,sr
	and.b	MIDI_Io_shadow_1.l,d2
	or.b	d1,d2
	move.b	d2,MIDI_Io_shadow_1.l
	move.b	d2,hw_MIDI_cont.w
	move	(sp)+,sr
L00356:
	move	$000C(sp),d2			;d2 = code for breaks (bit 3)
	bmi.s	L00384
	btst	#$03,d2
	beq.s	L00374
	ori.b	#$60,MIDI_Io_shadow_1.l
	move.b	MIDI_Io_shadow_1.l,hw_MIDI_cont.w
	bra.s	L00384

L00374:
	bclr	#$06,MIDI_Io_shadow_1.l
	move.b	MIDI_Io_shadow_1.l,hw_MIDI_cont.w
L00384:
	move	sr,d1
	swap	d1
	ori	#$0700,sr
	move	$0006(sp),d2			;d2 = code for flow control
	cmpi	#$0003,d2			;RTS/CTS and Xon/Xoff ?
	bhi.s	L003E6				;skip if code is too high
	bne.s	L0039A
	moveq	#$01,d2				;force RTC/CTS off
L0039A:
	cmpi	#$0002,d2			;RTS/CTS ?
	bne.s	L003A2
	moveq	#$00,d2				;force RTS/CTS off
L003A2:
	cmp.b	MIDI_Io_flow_ctr.l,d2
	beq.s	L003D4
	move.b	d2,MIDI_Io_flow_ctr.l
	clr	MIDI_Rx_locked_f.l
	cmpi.b	#$01,d2
	bne.s	L003D4
	btst	#$01,hw_MIDI_cont.w
	beq.s	L003CC
	move.b	#$11,hw_MIDI_data.w
	bra.s	L003D4

L003CC:
	move.b	#$11,MIDI_Tx_softnext.l
L003D4:
	bclr	#$04,hw_M1_aer.w
	ori.b	#$40,hw_M1_ierb.w
	ori.b	#$40,hw_M1_imrb.w
L003E6:
	swap	d1
	move	d1,sr
L003EA:
	rts

L003EC:
	moveq	#$00,d1
	cmpi.l	#$00007A12,d0
	bcs.s	L00400
	beq.s	L003FE
	move.l	#$80007A12,d0
L003FE:
	rts

L00400:
	moveq	#$01,d1
	cmpi.l	#$00001E84,d0
	beq.s	L003FE
	move.l	#$80001E84,d0
	rts

L00412:
	move.b	d1,MIDI_Io_baudcode.l
	moveq	#-$04,d2
	move	sr,-(sp)
	ori	#$0700,sr
	and.b	MIDI_Io_shadow_1.l,d2
	bset	d1,d2
	move.b	d2,hw_MIDI_cont.w
	move.b	d2,MIDI_Io_shadow_1.l
	move	(sp)+,sr
	rts
;----------------------------------------------------------------------------
;End of:	MAPTAB functions
;----------------------------------------------------------------------------
X00436:
	dc.b	$BE,$BC,$AE,$AC,$98,$88,$8E,$8C
;----------------------------------------------------------------------------
;Start of:	IOREC (for MAPTAB)
;----------------------------------------------------------------------------
MIDI_IOREC:
MIDI_Rx_buffer_p:	dc.l	start-$20	;$00
MIDI_Rx_size_ix:	dc.w	$0010		;$04
MIDI_Rx_head_ix:	dc.w	$0000		;$06
MIDI_Rx_tail_ix:	dc.w	$0000		;$08
MIDI_Rx_lo_fill:	dc.w	$0004		;$0A
MIDI_Rx_hi_fill:	dc.w	$000C		;$0C
MIDI_Tx_buffer_p:	dc.l	start-$10	;$0E
MIDI_Tx_size_ix:	dc.w	$0010		;$12
MIDI_Tx_head_ix:	dc.w	$0000		;$14
MIDI_Tx_tail_ix:	dc.w	$0000		;$16
MIDI_Tx_lo_fill:	dc.w	$0004		;$18
MIDI_Tx_hi_fill:	dc.w	$000C		;$1A
			dc.b	$00		;$1C
MIDI_Io_shadow_1:	dc.b	$B5		;$1D
MIDI_Rx_locked_f:	dc.w	$00		;$1E
			dc.b	$00		;$1F
MIDI_Io_flow_ctr:	dc.b	$00		;$20
MIDI_Tx_softnext:	dc.b	$00		;$21
MIDI_Io_baudcode:	dc.b	$00		;$22
			dc.b	$FF		;$23
MIDI_Io_baudrate:	dc.l	$00007A12	;$24
;----------------------------------------------------------------------------
;End of:	IOREC (for MAPTAB)
;----------------------------------------------------------------------------
;start of:	MX_DDEV driver functions
;----------------------------------------------------------------------------
MIDI_ddev_seek:
MIDI_ddev_open:
MIDI_ddev_close:
	moveq	#$00,d0
	rts
;----------------------------------------------------------------------------
MIDI_ddev_stat:
	moveq	#$01,d0
	tst.l	d1
	beq.s	L004D4
	moveq	#$00,d0
L004D4:
	move.l	a1,d1
	beq.s	L004DA
	move.l	d0,(a1)
L004DA:
	rts
;----------------------------------------------------------------------------
MIDI_ddev_delete:
	moveq	#-$20,d0
	rts
;----------------------------------------------------------------------------
MIDI_dev_pathname_s:
	dc.b	'u:\dev\midi_ser',$00
	even
;----------------------------------------------------------------------------
MIDI_dev_MX_DDEV:
	dc.l	MIDI_ddev_open,MIDI_ddev_close
	dc.l	MIDI_ddev_read,MIDI_ddev_write
	dc.l	MIDI_ddev_stat,MIDI_ddev_seek
	dc.l	$00000000,MIDI_ddev_ioctl	; datime undefined
	dc.l	MIDI_ddev_delete,$00000000	; getc undefined
	dc.l	$00000000,$00000000		; getline & putc undefined
;----------------------------------------------------------------------------
MIDI_ddev_read:
	moveq	#$00,d1				; clear high bits of d1
	lea	MIDI_IOREC.l,a2
	move	Rx_size_ix(a2),d2			; d2 = Rx_size_ix
	move	Rx_tail_ix(a2),d1		; d1 = Rx_tail_ix
	sub	Rx_head_ix(a2),d1			; d2 -= Rx_head_ix
	bcc.s	L00534				; if tail>head, keep positive d1
	add	d2,d1				; else d1 += Rx_size_ix
L00534:
	cmp.l	d0,d1				; available < wanted ?
	bcc.s	L0053A				; else use wanted count
	move.l	d1,d0				; d0 = available byte count
L0053A:
	tst.l	d0				; count != 0 ?
	beq.s	L00568				; else exit
	move.l	d0,-(sp)			; push count
	movea.l	(a2),a0				; a0 = Rx_buffer_p
	move	Rx_head_ix(a2),d1			; d1 = Rx_head_ix
	bra.s	.read_next			; enter loop for count-1 chars

.read_loop:
	addq	#1,d1				; d1 += 1
	cmp	d2,d1				; d1 >= Rx_size_ix ?
	bcs.s	.done_index_wrap
	moveq	#$00,d1				; d1 = zero index
.done_index_wrap:
	move.b	$00(a0,d1.l),(a1)+		; transfer byte to arg buffer
.read_next:
	subq.l	#1,d0				; decrement count
	bne.s	.read_loop			; loop for all but last char
	move	d1,Rx_head_ix(a2)			; Rx_head_ix = d1
	move.l	a1,-(sp)			; push -> arg buffer pos
	bsr.w	MIDI_Bconin			; use Bconin for last char
	movea.l	(sp)+,a1			; pull a1 -> arg buffer pos
	move.b	d0,(a1)				; store last char
	move.l	(sp)+,d0			; pull d0 = count
L00568:
	rts					; return to caller
;----------------------------------------------------------------------------
MIDI_ddev_write:
	moveq	#$00,d1				; clear high bits of d1
	lea	MIDI_IOREC.l,a2
	move	Tx_size_ix(a2),d2			; d2 = Tx_size_ix
	move	Tx_head_ix(a2),d1			; d1 = Tx_head_ix
	sub	Tx_tail_ix(a2),d1			; d1 -= Tx_tail_ix
	bhi.s	L00582				; if head>tail, keep positive d1
	add	d2,d1				; d1 += Tx_size_ix
L00582:
	subq.l	#2,d1				; d1 = safe_room
	bpl.s	L00588				; if positive, all is well
	moveq	#$00,d1				; else force d1 = 0
L00588:
	cmp.l	d0,d1				; safe_room < wanted ?
	bcc.s	L0058E				; else use wanted count
	move.l	d1,d0				; d0 = safe_room count
L0058E:
	tst.l	d0				; count != 0 ?
	beq.s	L005BE				; else exit
	move.l	d0,-(sp)			; push count
	movea.l	Tx_buffer_p(a2),a0		; a0 = Tx_buffer_p
	move	Tx_tail_ix(a2),d1		; d1 = Tx_tail_ix
	bra.s	L005AA				; enter loop for count-1 chars

L0059E:
	addq	#1,d1				; d1 += 1
	cmp	d2,d1				; d1 >= Tx_size_ix
	bcs.s	L005A6
	moveq	#$00,d1				; d1 = zero index
L005A6:
	move.b	(a1)+,$00(a0,d1.l)		; transfer byte from arg buffer
L005AA:
	subq.l	#1,d0				; decrement count
	bne.s	L0059E				; loop for all but last char
	move	d1,Tx_tail_ix(a2)		; Tx_tail_ix = d1
	move.b	(a1),d0				; d0 = last char
	move.l	d0,-(sp)			; push last char as arg
	bsr.w	MIDI_Bconout			; use Bconout for last char
	addq.l	#4,sp				; clean stack
	move.l	(sp)+,d0			; pull d0 = count
L005BE:
	rts					; return to caller
;----------------------------------------------------------------------------
MIDI_ddev_ioctl:
	cmpi	#$4601,d0
	beq.s	midi_FIONREAD
	cmpi	#$4602,d0
	beq.s	midi_FIONWRITE
	cmpi	#$5414,d0
	beq.w	midi_TIOCCBRK
	cmpi	#$5415,d0
	beq.w	midi_TIOCSBRK
	cmpi	#$5412,d0
	beq.w	midi_TIOCxBAUD
	cmpi	#$5413,d0
	beq.w	midi_TIOCxBAUD
	cmpi	#$5416,d0
	beq.w	midi_TIOCGFLAGS
	cmpi	#$5417,d0
	beq.w	midi_TIOCSFLAGS
	cmpi	#$5481,d0
	beq.w	midi_TIOCCTLMAP
	cmpi	#$5482,d0
	beq.w	midi_TIOCCTLGET
	cmpi	#$5483,d0
	beq.w	midi_TIOCCTLSET
	cmpi	#$5486,d0
	beq.w	midi_TIONOTSEND
	cmpi	#$5408,d0
	beq.w	midi_TIOCFLUSH
	moveq	#-$20,d0
	bra.s	exit_ioctl_d0

exit_ioctl_OK:
	moveq	#$00,d0
exit_ioctl_d0:
	rts

midi_FIONREAD:
	moveq	#$00,d1
	move	MIDI_Rx_tail_ix.l,d1
	sub	MIDI_Rx_head_ix.l,d1
	bcc.s	L00642
	add	MIDI_Rx_size_ix.l,d1
L00642:
	move.l	d1,(a1)
	bra.s	exit_ioctl_OK

midi_FIONWRITE:
	moveq	#$00,d1
	move	MIDI_Tx_head_ix.l,d1
	sub	MIDI_Tx_tail_ix.l,d1
	bhi.s	L0065C
	add	MIDI_Tx_size_ix.l,d1
L0065C:
	subq.l	#2,d1
	bpl.s	L00662
	moveq	#$00,d1
L00662:
	move.l	d1,(a1)
	bra.s	exit_ioctl_OK

midi_TIOCCBRK:
	bclr	#$06,MIDI_Io_shadow_1.l
	move.b	MIDI_Io_shadow_1.l,hw_MIDI_cont.w
	bra.s	exit_ioctl_OK

midi_TIOCSBRK:
	ori.b	#$60,MIDI_Io_shadow_1.l
	move.b	MIDI_Io_shadow_1.l,hw_MIDI_cont.w
	bra.s	exit_ioctl_OK

midi_TIOCxBAUD:
	move.l	(a1),d0
	bpl.s	L006A4
L0068E:
	move.l	a1,-(sp)
	moveq	#-$01,d0
	move.l	d0,-(sp)
	move	#-$012C,-(sp)
	bsr.w	MIDI_Rsconf
	addq.l	#6,sp
	movea.l	(sp)+,a1
	move.l	d0,(a1)
	bra.s	exit_ioctl_OK

L006A4:
	bne.s	L006AC
	bsr.w	L007A8
	bra.s	L0068E

L006AC:
	move.l	a1,-(sp)
	move.l	d0,-(sp)
	move	#-$012C,-(sp)
	bsr.w	MIDI_Rsconf
	addq.l	#6,sp
	movea.l	(sp)+,a1
	bclr	#$1F,d0
	beq.s	L006CA
	move.l	d0,(a1)
	moveq	#-$40,d0
	bra.w	exit_ioctl_d0

L006CA:
	move.l	d0,(a1)
	bsr.w	L007A6
	bra.w	exit_ioctl_OK

midi_TIOCGFLAGS:
	moveq	#$1C,d2
	and.b	MIDI_Io_shadow_1.l,d2
	lsr	#1,d2
	move	L006F6(pc,d2),d1
	moveq	#$03,d0
	and.b	MIDI_Io_flow_ctr.l,d0
	moveq	#$0C,d2
	lsl	d2,d0
	or	d0,d1
	move	d1,(a1)
	bra.w	exit_ioctl_OK

L006F6:
	negx.b	d7
	or.b	d7,d0
	negx.b	d5
	or.b	d5,d0
	ori.b	#$01,d3
	negx.b	d1
	or.b	d1,d0
midi_TIOCSFLAGS:
	move	(a1),d2
	andi	#-$3001,d2
	moveq	#$0E,d1
L0070E:
	cmp	L006F6(pc,d1),d2
	beq.s	L0071E
	subq	#2,d1
	bpl.s	L0070E
	moveq	#-$40,d0
	bra.w	exit_ioctl_d0

L0071E:
	lsl.b	#1,d1
	moveq	#-$1D,d2
	move	sr,-(sp)
	ori	#$0700,sr
	and.b	MIDI_Io_shadow_1.l,d2
	or.b	d1,d2
	move.b	d2,MIDI_Io_shadow_1.l
	move.b	d2,hw_MIDI_cont.w
	move	(sp)+,sr
	moveq	#-$01,d0
	move.l	d0,-(sp)
	move.l	d0,-(sp)
	move	(a1),d2
	moveq	#$0C,d1
	lsr	d1,d2
	andi	#$0003,d2
	move	d2,-(sp)
	move	d0,-(sp)
	moveq	#-$40,d0
	subq	#2,d2
	beq.s	L0075C
	bsr.w	MIDI_Rsconf
	moveq	#$00,d0
L0075C:
	lea	$000C(sp),sp
	bra.w	exit_ioctl_d0

midi_TIOCCTLMAP:
	move.l	#$00001000,(a1)+
	moveq	#$00,d0
	move.l	d0,(a1)+
	move.l	d0,(a1)+
	move.l	d0,(a1)+
	move.l	d0,(a1)+
	move.l	d0,(a1)+
	bra.w	exit_ioctl_OK

midi_TIOCCTLGET:
	moveq	#$00,d0
	lea	MIDI_IOREC.l,a2
	move	#$1000,d1
	and	$0002(a1),d1
	beq.s	L0079A
	moveq	#$70,d2
	and.b	Io_shadow_0(a2),d2
	beq.s	L0079A
	eor.b	d2,Io_shadow_0(a2)
	or	d1,d0
L0079A:
	move.l	d0,(a1)
	bra.w	exit_ioctl_OK

midi_TIOCCTLSET:
	move.l	(a1),d0
	bra.w	exit_ioctl_OK

L007A6:
	rts

L007A8:
	rts

midi_TIONOTSEND:
	bsr.w	L0083C
	move.l	d0,(a1)
	bra.w	exit_ioctl_OK

midi_TIOCFLUSH:
	move.l	a1,d0
	bmi.s	L007C8
	beq.s	L007E4
	cmpi.l	#$00000004,d0
	bcs.s	L007EC
	moveq	#-$20,d0
	bra.w	exit_ioctl_d0

L007C8:
	moveq	#$00,d2
	sub.l	d0,d2
L007CC:
	add.l	_hz_200.w,d2
L007D0:
	bsr.s	L0083C
	tst.l	d0
	beq.w	exit_ioctl_OK
	cmp.l	_hz_200.w,d2
	bcc.s	L007D0
	moveq	#-$02,d0
	bra.w	exit_ioctl_d0

L007E4:
	move.l	#4000,d2
	bra.s	L007CC

L007EC:
	btst	#$01,d0
	beq.s	L007F8
	clr.l	MIDI_Tx_head_ix.l
L007F8:
	btst	#$00,d0
	beq.s	L00838
	clr.l	MIDI_Rx_head_ix.l
	move.b	MIDI_Io_flow_ctr.l,d1
	beq.s	L00838
	sf	MIDI_Rx_locked_f.l
	move	sr,d2
	ori	#$0700,sr
	btst	#$01,d1
	beq.s	L00820
	bra.s	L00836

L00820:
	moveq	#$11,d1
	btst	#$01,hw_MIDI_cont.w
	beq.s	L00830
	move.b	d1,hw_MIDI_data.w
	moveq	#$00,d1
L00830:
	move.b	d1,MIDI_Tx_softnext.l
L00836:
	move	d2,sr
L00838:
	bra.w	exit_ioctl_OK

L0083C:
	moveq	#$00,d0
	move	MIDI_Tx_tail_ix.l,d0
	sub	MIDI_Tx_head_ix.l,d0
	bcc.s	L00852
	add	MIDI_Tx_size_ix.l,d0
L00852:
	btst	#$01,hw_MIDI_cont.w
	bne.s	L0085C
	addq.l	#1,d0
L0085C:
	rts
;----------------------------------------------------------------------------
;End of:	MX_DDEV driver functions
;----------------------------------------------------------------------------
MIDI_dev_name_s:
	dc.b	'MIDI_SER',$00,$00
;-------------------------------------
MIDI_RSVF:
	dc.l	MIDI_dev_name_s
	dc.b	$E0,$00
X0086A:
	dc.b	$06,$00
;-------------------------------------
X0086C:
	dc.l	$00000000,$00000000
;-------------------------------------
next_BUF_p:
	dc.l	init_2_supx
	dc.w	$0000,$0000
;----------------------------------------------------------------------------
BM_0087C:	; All code below is overwritten by buffers
init_2_supx:
	move.b	#$03,hw_MIDI_cont.w
	move.l	iv_M1_kb_midi.w,ol_iv_M1_kb_midi_p
	move.l	#nu_iv_M1_kb_midi,iv_M1_kb_midi.w
	move.l	#$0085FFFF,-(sp)
	move.l	#$008A0001,-(sp)
	move.l	#$00000000,-(sp)
	bsr.w	MIDI_Rsconf
	lea	$000C(sp),sp
	rts
;----------------------------------------------------------------------------
find_RSVF_cookie_supx:
	move.l	#$52535646,-(sp)		; push #'RSVF'
	bsr.w	find_cookie_supx
	addq.l	#4,sp
	tst.l	d0
	sne	RSVF_found_f.l
	beq.s	L00934
	movea.l	d0,a0
	movea.l	Rx_size_ix(a0),a1
	tst.l	Rx_size_ix(a1)
	bmi.s	L00926
	movea.l	(a1),a1
L00926:
	move.l	a1,X0086C.l
	move.l	#MIDI_RSVF,Rx_size_ix(a0)
L00934:
	rts
;----------------------------------------------------------------------------
init_1:
	bsr.w	disp_imm
	dc.b	$1B,'pFast routines for MIDI.',$1B
	dc.b	'q',$0D,$0A
	dc.b	'(C) SWB Harun Scheutzow 1995-04-28',$0D
	dc.b	$0A,$00
	move	#$0022,-(sp)	; Kbdvbase
	trap	#14		; Xbios
	addq.l	#2,sp
	add.l	d0,Kbdvbase_ikbd_vec_p.l
	pea	init_2_supx.l
	move	#$0026,-(sp)	; Supexec
	trap	#14		; Xbios
	addq.l	#6,sp
	pea	MIDI_MAPTAB.l
	move	#-$0191,-(sp)			; push #$FE6F (HSM_BCON_INSTALL)
	move	#$002C,-(sp)	; Bconmap
	trap	#14		; Xbios
	addq.l	#8,sp
	tst.l	d0
	bne.s	L009DA
	bsr.w	disp_imm
	dc.b	'ERROR: Load DRVIN.PRG first!(?)',$07
	dc.b	$07,$07,$07,$0D,$0A,$00
	bra.s	L00A46

L009DA:
	move.b	d0,X0086A.l
	moveq	#$01,d7
	bra.s	L009F2

L009E4:
	pea	MIDI_dev_pathname_s.l
	move	#$0041,-(sp)	; Fdelete
	trap	#1		; Gemdos
	addq.l	#6,sp
L009F2:
	pea	MIDI_dev_MX_DDEV.l
	pea	MIDI_dev_pathname_s.l
	move	#-$3300,-(sp)			; push #$CD00 (DEV_M_INSTALL)
	move	#$0130,-(sp)	; Dcntl
	trap	#1		; Gemdos
	lea	$000C(sp),sp
	tst.l	d0
	dbpl	d7,L009E4
	pea	find_RSVF_cookie_supx.l
	move	#$0026,-(sp)	; Supexec
	trap	#14		; Xbios
	addq.l	#6,sp
	tst.b	RSVF_found_f.l
	bne.s	L00A46
	bsr.s	disp_imm
	dc.b	'Cookie RSVF not found',$07
	dc.b	$07,$07,$07,$0D,$0A,$00
L00A46:
	bsr.s	disp_imm
	dc.b	$0D,$0A,$00,$00
	lea	patch_buffer_sizes.l,a0
	lea	final_patch_loc.l,a1
	move.l	#$0000007F,d0
L00A5E:
	move.b	$00(a0,d0.l),$00(a1,d0.l)
	subq.l	#1,d0
	bpl.s	L00A5E
	pea	clear_CPU_cache.l
	move	#$0026,-(sp)	; Supexec
	trap	#14		; Xbios
	addq.l	#6,sp
	jmp	final_patch_loc.l
;----------------------------------------------------------------------------
disp_imm:
	move.l	(sp),-(sp)
	move	#$0009,-(sp)	; Cconws
	trap	#1		; Gemdos
	addq.l	#6,sp
	movea.l	(sp)+,a0
L00A88:
	tst.b	(a0)+
	sne	d0
	and.b	(a0)+,d0
	bne.s	L00A88
	jmp	(a0)
;----------------------------------------------------------------------------
find_cookie_supx:
	move.l	$0004(sp),d1
	move.l	_cookies.w,d0
	beq.s	L00AAC
	movea.l	d0,a0
L00A9E:
	move.l	(a0),d0
	beq.s	L00AAC
	cmp.l	d0,d1
	beq.s	L00AAA
	addq.l	#8,a0
	bra.s	L00A9E

L00AAA:
	move.l	a0,d0
L00AAC:
	rts
;----------------------------------------------------------------------------
	movem.l	d2/a2,-(sp)
	move.l	_cookies.w,d0
	beq.w	L00B46
	move.l	$000C(sp),-(sp)
	bsr.s	find_cookie_supx
	addq.l	#4,sp
	movea.l	d0,a0
	tst.l	d0
	bne.s	L00B38
	movea.l	_cookies.w,a0
	moveq	#$00,d2
L00ACE:
	move.l	$00(a0,d2.l),d1
	beq.s	L00AD8
	addq.l	#8,d2
	bra.s	L00ACE

L00AD8:
	lea	$00(a0,d2.l),a1
	lsr.l	#3,d2
	addq.l	#1,d2
	move.l	$0004(a1),d1
	moveq	#-$01,d0
	cmp.l	d1,d2
	bcc.s	L00AFC
	clr.l	$0008(a1)
	move.l	d1,$000C(a1)
	move.l	$000C(sp),(a1)+
	move.l	$0010(sp),(a1)+
	bra.s	L00B40

L00AFC:
	move.l	$0014(sp),d0
	beq.s	L00B40
	movea.l	d0,a2
	move.l	a1,d2
	sub.l	a0,d2
	addi.l	#$00000050,d2
	moveq	#$00,d0
	cmp.l	$0018(sp),d2
	bhi.s	L00B40
L00B16:
	move.l	(a0)+,(a2)+
	move.l	(a0)+,(a2)+
	cmpa.l	a1,a0
	bcs.s	L00B16
	addq.l	#4,d1
	addq.l	#5,d1
	move.l	d2,d0
	move.l	$000C(sp),(a2)+
	move.l	$0010(sp),(a2)+
	clr.l	(a2)+
	move.l	d1,(a2)+
	move.l	$0014(sp),_cookies.w
	bra.s	L00B40

L00B38:
	move.l	$0010(sp),Rx_size_ix(a0)
	moveq	#-$01,d0
L00B40:
	movem.l	(sp)+,d2/a2
	rts

L00B46:
	move.l	$0014(sp),d0
	beq.s	L00B40
	movea.l	d0,a0
	moveq	#$00,d0
	move.l	#$00000062,d2
	cmp.l	$0018(sp),d2
	bhi.s	L00B40
	lea	L00BA6(pc),a2
	move.l	resvector.w,$000C(a2)
	move.l	resvalid.w,$0000(a2)
	move.l	#$00000021,d0
	movea.l	a0,a1
L00B74:
	move.b	(a2)+,(a1)+
	dbf	d0,L00B74
	move.l	a1,d0
	move.l	$000C(sp),(a1)+
	move.l	$0010(sp),(a1)+
	clr.l	(a1)+
	move.l	#$00000008,(a1)
	adda.l	#$00000010,a0
	move.l	a0,resvector.w
	move.l	#$31415926,resvalid.w
	move.l	d0,_cookies.w
	move.l	d2,d0
	bra.s	L00B40
;----------------------------------------------------------------------------
L00BA6:
	dc.l	0
;----------------------------------------------------------------------------
	dc.l	'XBRA'
	dc.l	'CKJR'
L00BB2:
	dc.l	0
	clr.l	_cookies.w
	move.l	L00BB2(pc),resvector.w
	move.l	L00BA6(pc),resvalid.w
	jmp	(a6)
;----------------------------------------------------------------------------
clear_CPU_cache:
	move.l	d0,-(sp)
	move.l	a0,-(sp)
	move.l	_cookies.w,d0
	beq.s	done_clear_cache
	movea.l	d0,a0
L00BD4:
	move.l	(a0),d0
	beq.s	done_clear_cache
	addq.l	#8,a0
	cmpi.l	#$5F435055,d0			; '_CPU' ?
	bne.s	L00BD4
	move	-(a0),d0
	cmpi	#$0014,d0			; 68020 ?
	bcs.s	done_clear_cache
	cmpi	#$0028,d0			; 68040 ?
	bcc.s	clear_cache_040
	movec	cacr,d0
	ori	#$0808,d0
	movec	d0,cacr				; clear 68030 or 68020 cache
	bra.s	done_clear_cache

clear_cache_040:
	dc.w	$F478				; $F478 == 68040 'cpusha DC'
	dc.w	$F498				; $F498 == 68040 'cinva  IC'
	nop
done_clear_cache:
	movea.l	(sp)+,a0
	move.l	(sp)+,d0
	rts
;----------------------------------------------------------------------------
MIDI_MAPTAB:
	dc.l	MIDI_Bconstat,MIDI_Bconin
	dc.l	MIDI_Bcostat,MIDI_Bconout
	dc.l	MIDI_Rsconf,MIDI_IOREC
;----------------------------------------------------------------------------
X00C22:
	dc.b	'hAruNs cONfigER',$00
	dc.l	X00C22
cnf_RBL_entry:
	dc.b	'RBL: Einstellung der Empfangspuffergr',$94
	dc.b	$9E,'e in Byte.',$0D
	dc.b	$0A,'Standard: 256,  Minimum: 16,  Maximum: 65534',$0D
	dc.b	$0A,$00
	even
	dc.w	$0101
RBL_size:
	dc.l	16384
cnf_TBL_entry:
	dc.b	'TBL: Einstellung der Sendepuffergr',$94,$9E
	dc.b	'e in Byte.',$0D,$0A
	dc.b	'Standard: 256,  Minimum: 16,  Maximum: 65534',$0D,$0A
	dc.b	$00
	even
	dc.w	$0101
TBL_size:
	dc.l	4096
cnf_END_entry:
	dc.b	NUL
	even
;----------------------------------------------------------------------------
patch_buffer_sizes:
	move.l	RBL_size.l,d0
	move.l	TBL_size.l,d7
	lea	MIDI_IOREC.l,a0
	bsr.s	add_buffer
	lea	MIDI_Tx_buffer_p.l,a0
	move.l	d7,d0
	bsr.s	add_buffer
	clr	-(sp)
	move.l	next_BUF_p.l,d0
	subi.l	#start-$100,d0
	move.l	d0,-(sp)
	move	#$0031,-(sp)	; Ptermres
	trap	#1		; Gemdos
;----------------------------------------------------------------------------
add_buffer:
	move.l	#$00000100,d1
	andi.l	#$FFFFFFFE,d0
	cmpi.l	#$80000000,d0
	beq.s	L00DEE
	cmpi.l	#$0000FFFE,d0
	bhi.s	L00DEE
	cmpi.l	#$00000010,d0
	bcs.s	L00DEE
	move	d0,d1
L00DEE:
	move.l	next_BUF_p.l,Rx_buffer_p(a0)
	add.l	d1,next_BUF_p.l
	move	d1,Rx_size_ix(a0)
	clr.l	Rx_head_ix(a0)
	move	d1,d0
	lsr	#2,d1
	move	d1,Rx_lo_fill(a0)
	sub	d1,d0
	move	d0,Rx_hi_fill(a0)
	rts
;----------------------------------------------------------------------------
	BSS
;----------------------------------------------------------------------------
	ds.b	$20000
RSVF_found_f:
	ds.b	$00000002
final_patch_loc:
	ds.b	$00001080
U21E96:
	end	
;----------------------------------------------------------------------------
; End of file:	MIDI_SER.S
;----------------------------------------------------------------------------
