page	55,96
title	SDA_USR2  -  Stand-alone routines for the SDA Midicard.

.XLIST
INCLUDE		DOS.MAC
.LIST

; Revisions:
;
;	01-8-88		Added dummy 'mov ax,0' instructions in _U_LOC_MC
;			to provide settle time when running in 10mh AT's
;	04-19-88	Added addr. 320 (MPU mode) support.

; This file is a MICROSOFT C linkable version of SDA_USR2.ASM that uses
; the segment macros in DOS.MAC.  It is compatible with MICROSOFT C v3.0+.


;******************************************************************
;*
;* See companion file 'SDA_USER.DOC' for more information on 
;* these subroutines.
;*
;******************************************************************




;******************************************************************
;*
;* This software is intended to provide access to a Downloaded
;* Systems Design Midicard such that it may be used in UART mode.
;* In this mode the interface (Midicard) will send all data
;* received from Midi IN to the host PC, and will send all data
;* from the host out MIdi OUT.  There is no direct flow of data
;* from Midi IN to Midi OUT (Midi THRU) in the Midicard in UART mode.
;* THRU capabilities must be handled by the host in this mode.
;*
;* These routines are NOT designed to be memory resident with a
;* running Promidi system.  Routines that provide services for
;* memory co-resident software (TSR) are provided as public 
;* domain 8086 assembly source in "SDA_USER.ASM".
;*
;* The following requirments must be satisfied before data may be
;* sent and received from a Midicard:
;* 
;*	1. The Midicard must be downloaded.
;*
;*	The loader program is MLOAD.EXE and the Midicard's software
;*	is in file Z8.HEX.  Both of these programs are supplied with
;*	with every Promidi system.  Before Promidi can run, the
;*	command line "MLOAD Z8" is executed (from BATCH file SDA.BAT).
;*	Once the Midicard's program has been downloaded, it is intact
;*	until the PC is powered down.  The same "MLOAD Z8" may be used
;*	in any batch file to download the Midicard.
;*
;*
;*	2. The Midicard must be located and initialized.
;*
;*	There is a file called SDA.CFG that is in the same directory
;*	as MLOAD.EXE and Z8.HEX.  This file contains (along with other data)
;*	the switch settings set by the user at instalation time that
;*	position the card in the PC's I/O space and assign it one of
;*	four interrupt addresses.
;*
;*	The provided routine "_U_LOC_MC" is used to locate the Midicard.
;*
;*
;* After these requirments have been satisfied, the I/O routines 
;* may be called.
;*
;* Before terminating, the software should ALWAYS call _U_EXIT which
;* will reset (deactivate) the Midicard. 
;*
;******************************************************************


;*************************************************************************
;*
;* The source file 'TST_USR2.ASM' is provided free of charge by Systems 
;* Design Associates, Inc.  SDA does not in any way warranty this software 
;* nor is it liable for any damages resulting from its use.
;*
;*************************************************************************

	DSEG


; MIDICARD 8255 REG. DEFINITION
; MUST CORRESPOND TO SW. 1-4 ON MIDICARD

PTA	DW	?
PTB	DW	?
PTC	DW	?
PTCNTL	DW	?



; MIDICARD INTERRUPT INFO. 
; MUST CORRESPOND TO SW 5-8 ON MIDICARD

MI_LOC	DW	?
MI_BIT	DB	?

FILEBUF	DB	?,?
FILESTR	DB	'SDA.CFG'
	DB	0

	ENDDS


	PSEG


PUBLIC	_U_LOC_MC,_U_SNDB,_U_RCVB,_U_EXIT,_U_TRCV
page



; _U_LOC_MC
;
;      THIS ROUTINE MUST BE CALLED SUCCESSFULLY (RET = 1)
;      IN ORDER TO USE "_U_SNDB" and "_U_RCVB".
;
; If the file SDA.CFG is found in the current directory,
;  this routine fills the port and interrupt location data used
;  by the I/O routines.
;
;	Returns:	ax = 0		Error.
;			ax = 1		Completed.
;
;	Regs altered - ax,bx,cx,dx

_U_LOC_MC proc far
	push	si
	mov	dx,offset DGROUP:FILESTR	; Open SDA.CFG for reading.
	mov	ax,3D00H
	int	21H
	jnc	ULOC1
	xor	ax,ax			; Error
	jmp	ULOCRET	
ULOC1:
	mov	si,ax			; Save file handle in SI
	mov	bx,ax			; Read first two bytes in SDA.CFG
	mov	cx,2
	mov	dx,offset DGROUP:FILEBUF
	mov	ax,3F00H
	int	21H
	jnc	ULOC2
	xor	ax,ax			; Error
	jmp	ULOCRET	
ULOC2:
	mov	bx,si			; Close the file
	mov	ax,3E00H	
	int	21H

	mov	si,offset DGROUP:FILEBUF
	mov	al,[si]			; Get 1st byte 

	mov	bx,300H
	dec	al
	jz	ULOC3

	mov	bx,280H
	dec	al
	jz	ULOC3

	mov	bx,240H
	dec	al
	jz	ULOC3

	mov	bx,220H
	dec	al
	jz	ULOC3

	mov	bx,320H			; MPU mode
	dec	al
	jz	ULOC3

	xor	ax,ax			; Error
	jmp	ULOCRET	
ULOC3:	
	mov	PTA,bx			; Set up port addresses
	inc	bx
	mov	PTB,bx
	inc	bx
	mov	PTC,bx
	inc	bx
	mov	PTCNTL,bx

	inc	si
	mov	al,[si]			; Get 2nd byte
	sub	al,4

	mov	MI_LOC,(8 + 2) * 4	; Set up interrupt address
	mov	MI_BIT,04H
	dec	al
	jz	ULOC4

	mov	MI_LOC,(8 + 7) * 4
	mov	MI_BIT,80H
	dec	al
	jz	ULOC4

	mov	MI_LOC,(8 + 5) * 4
	mov	MI_BIT,20H
	dec	al
	jz	ULOC4

	mov	MI_LOC,(8 + 4) * 4
	mov	MI_BIT,10H
	dec	al
	jz	ULOC4
	xor	ax,ax			; Error
	jmp	ULOCRET	
ULOC4:	
	pushf
	cli

	call	INS_MCMODE		; Make sure we're in Midicard Mode

	mov	dx,PTC
	mov	al,1			; Midicard mode
	mov	ah,0			; wait
	mov	ah,0
	out	dx,al

	mov	al,0C1H
	mov	ah,0			; wait
	mov	ah,0
	out	dx,al

	mov	dx,PTCNTL		; Change of mode in 8255 will put
	mov	al,0C2H 		;  us in MPU mode.
	mov	ah,0			; wait
	mov	ah,0
	out	dx,al

	call	INS_MCMODE

	mov	al,0FH
	mov	ah,0			; wait
	mov	ah,0
	out	dx,al

	mov	al,9
	mov	ah,0			; wait
	mov	ah,0
	out	dx,al
	mov	ax,1
	popf
	xor	ax,ax
ULOC6:
	dec	ax
	jnz	ULOC6
ULOC5:
	mov	dx,PTC
	in	al,dx
	test	al,80H
	jz	ULOC5

	mov	dx,PTCNTL
	mov	al,5
	out	dx,al

	mov	dx,PTA
	mov	al,35
	out	dx,al
ULOCRET:
	pop	si
	ret
_U_LOC_MC endp
PAGE

; INS_MCMODE
;
; INSURE THAT THE MIDICARD IS IN MIDICARD MODE 

INS_MCMODE	PROC	NEAR

; TEST FOR EXPANDER

	MOV  AX, PTA
 	CMP  AX, 0320H
	JNE  NOEXP1

; PUT CARD IN MIDICARD MODE - SET PORT C, BIT 0.

	MOV  DX, PTC
	ADD  DX, 010H		; PORTS MAY HAVE BEEN SHIFTED UP 10H.
	MOV  AL, 0C1H
	OUT  DX, AL
NOEXP1:
	RET

INS_MCMODE ENDP

page




; _U_RCVB  -  If a byte is present, receive a byte from the Midicard
;
;  c  call	c = u_rcvb();
;
;  asm  call	call	_u_rcvb	; Byte or ret. code in ax.  
;    (far)
;
;	RETURNS:	byte
;			100H		No input received
;
;	Regs Altered: ax,dx

_U_RCVB	proc	far
	mov	dx,PTC
	in	al,dx
	test	al,20H			; Look for input
	jnz	IBFULL
	mov	ax,100H			; None
	jmp	URCRET
IBFULL:
	mov	dx,PTA			; Get byte
	in	al,dx
	xor	ah,ah
URCRET:
	ret
_U_RCVB	endp
page




; _U_TRCV  -  Test if a byte is present from the Midicard
;
;  c  call	rc = u_trcv();
;
;  asm  call	call	_u_trcv  ; Ret. code in ax.  
;    (far)
;
;	RETURNS:	0		No input.
;			1		Input present.
;
;	Regs Altered: ax,dx

_U_TRCV	proc	far
	mov	dx,PTC
	in	al,dx
	test	al,20H			; Look for input
	jnz	UTR1
	xor	ax,ax
	jmp	UTRRET
UTR1:
	mov	ax,1
UTRRET:
	ret
_U_TRCV	endp
page





; _U_SNDB  -  Send a byte to the Midicard.
;
;  c call	u_sndb(c);
;
;  asm call	push	ax		; Push byte on stack
;   (far)	call	_u_sndb
;		add	sp,2
;
;
;	Regs Altered: ax,cx,dx

_U_SNDB	proc	far
	push	bp
	mov	bp,sp
	mov	cx,[bp+6]		; Get parameter.
USND1:
	mov	dx,PTC
	in	al,dx
	test	al,80H			; Output buffer empty ?
	jz	USND1			; No - keep trying.

	mov	dx,PTB
	in	al,dx
	test	al,40H			; Can we send Midi data ?
	jnz	USND1			; No - keep trying.

	mov	dx,PTCNTL		; Say its Midi data
	mov	al,4			;   (not a command)
	out	dx,al

	mov	dx,PTA			; Send byte.
	mov	al,cl
	out	dx,al

	pop	bp
	ret
_U_SNDB	endp
page





; _U_EXIT  -  Reset th Midicard before terminating program.
;
;  c call	u_exit();
;
;  asm call	call	_u_exit
;   (far)
;
;
;	Regs Altered: ax,cx,dx

_U_EXIT	proc	far
	pushf
	cli
	mov	dx,PTC
	mov	al,1			; Midicard mode
	out	dx,al
	popf
	ret
_U_EXIT	endp


	ENDPS

	END
