/***************************************************************************
*	NAME:  IRQ16.C
**	COPYRIGHT:
**	"Copyright (c) 1994, by FORTE
**
**       "This software is furnished under a license and may be used,
**       copied, or disclosed only in accordance with the terms of such
**       license and with the inclusion of the above copyright notice.
**       This software or any other copies thereof may not be provided or
**       otherwise made available to any other person. No title to and
**       ownership of the software is hereby transfered."
****************************************************************************
*  CREATION DATE: 01/01/94
*--------------------------------------------------------------------------*
*     VERSION	DATE	   NAME		DESCRIPTION
*>	1.0	01/01/94		Original
***************************************************************************/

#include <stdio.h>
#include <dos.h>
#include <conio.h>

#include "forte.h"
#include "gf1proto.h"
#include "osproto.h"
#include "proto16.h"

/* internal include files */
#include "gf1hware.h"
#include "codec.h"
#include "dma.h"
#include "irq.h"
#include "gf1os.h"
#include "codecos.h"

/* #pragma inline */

extern IRQ_ENTRY _gf1_irq[];
extern DMA_ENTRY _gf1_dma[];
extern ULTRA16_DATA _codec_data;
extern IMAGE16 _image_codec;
extern PVI gf1_getvect();
extern ULTRA_DATA _gf1_data;

void
ReSet16IrqHandlers(codec_irq)
int codec_irq;
{
int temp_irq;

	temp_irq = codec_irq;

	if (temp_irq != 0)
		{
		if (codec_irq > 7)
			codec_irq += 0x68;
		else
			codec_irq += 0x08;

		gf1_setvect (codec_irq,_codec_data.old_codec_vec);
		}
}

void
Ultra16EnableIrqs()
{
ENTER_CRITICAL;
	/* enable IRQS from CODEC ... */
	outp(_codec_data.addr,IRQ_STATUS);
	outp(_codec_data.data,0);

	outp(_codec_data.status,0);		/* part of clearing IRQ ... */

	_image_codec.pc = IRQ_ENABLE;
	outp(_codec_data.addr,PIN_CTRL);
	outp(_codec_data.data,_image_codec.pc);	
LEAVE_CRITICAL;
}

void
Ultra16DisableIrqs()
{
ENTER_CRITICAL;
	/* enable IRQS from CODEC ... */
	outp(_codec_data.addr,IRQ_STATUS);
	outp(_codec_data.data,0);

	outp(_codec_data.status,0);		/* part of clearing IRQ ... */

	_image_codec.pc &= ~IRQ_ENABLE;
	outp(_codec_data.addr,PIN_CTRL);
	outp(_codec_data.data,_image_codec.pc);	
LEAVE_CRITICAL;
}

void
Set16Irqs(codec_irq)
int codec_irq;
{
unsigned char val;

ENTER_CRITICAL;

	if (codec_irq != 0)
		{
		/* unmask gf1 interrupt */
		val = inp(_gf1_irq[codec_irq].imr);
		val &= _gf1_irq[codec_irq].mask;
		outp(_gf1_irq[codec_irq].imr,val);

		/* send a specific EOI in case of pending interrupt */
		outp(_gf1_irq[codec_irq].ocr,_gf1_irq[codec_irq].spec_eoi);
		}

	/* Un-mask IRQ 2 from first controller if using 2nd controller */
	if (codec_irq > 7)
		{
		val = inp(_gf1_irq[2].imr);
		val &= _gf1_irq[2].mask;
		outp(_gf1_irq[2].imr,val);
		/* send a specific EOI in case of pending interrupt */
		outp(_gf1_irq[2].ocr,_gf1_irq[2].spec_eoi);
		}
	Ultra16EnableIrqs();

LEAVE_CRITICAL;
}

void
Reset16Irqs(codec_irq)
int codec_irq;
{
unsigned char val;

ENTER_CRITICAL;

	/* unmask gf1 interrupt */
	if ((codec_irq != 2) && (codec_irq != 0))
		{
		/* turn mask bit back on ... */
		val = inp(_gf1_irq[codec_irq].imr);
		val |= ~_gf1_irq[codec_irq].mask;
		outp(_gf1_irq[codec_irq].imr,val);
		}
LEAVE_CRITICAL;
}

static void
codec_handler()
{
unsigned char status;
DMA_ENTRY *tdma;

ENTER_CRITICAL;

	outp(_codec_data.addr,IRQ_STATUS);
	status = inp(_codec_data.data);
	status &= PLAYBACK_IRQ|CAPTURE_IRQ|TIMER_IRQ;

	if (status & PLAYBACK_IRQ)
		{
		tdma = &_gf1_dma[_codec_data.play_chan-1];
		tdma->flags &= ~DMA_PENDING;
		/* show foreground its done */
		_codec_data.flags &= ~DRAM_DMA_BUSY;

		_codec_data.playback_func();
		outp(_codec_data.addr,IRQ_STATUS);
		outp(_codec_data.data,(CAPTURE_IRQ|TIMER_IRQ));
		}

	if (status & CAPTURE_IRQ)
		{
		tdma = &_gf1_dma[_codec_data.rec_chan-1];
		tdma->flags &= ~DMA_PENDING;
		/* show foreground its done */
		_codec_data.flags &= ~ADC_DMA_BUSY;

		_codec_data.capture_func();
		outp(_codec_data.addr,IRQ_STATUS);
		outp(_codec_data.data,(PLAYBACK_IRQ|TIMER_IRQ));
		}

	if (status & TIMER_IRQ)
		{
		_codec_data.timer_func();
		outp(_codec_data.addr,IRQ_STATUS);
		outp(_codec_data.data,(PLAYBACK_IRQ|CAPTURE_IRQ));
		}

LEAVE_CRITICAL;
}

void
UltraMaxHandler()
{
if (inp(_codec_data.status) & CODEC_INT)
	{
	codec_handler();		/* Go to handler */
	}
}

#ifdef METAWARE
static _Far _INTERRPT void
#else
static void interrupt
#endif
codec_irq_handler()
{
int irq_num;

/* is it our handler ?? */
if (inp(_codec_data.status) & CODEC_INT)
	{
	irq_num = _codec_data.irq_num;
	/* clear PC's interrupt controller(s) */
	outp(_gf1_irq[irq_num].ocr,_gf1_irq[irq_num].spec_eoi);

	/* gotta send EOI to BOTH controllers */
	if (irq_num > 7)
		outp(OCR1,EOI);

	codec_handler();		/* Go to handler */
	}
}

void
Set16IrqHandlers(codec_irq)
int codec_irq;
{
int temp_irq;

ENTER_CRITICAL;

	temp_irq = codec_irq;

	if (temp_irq != 0)
		{
		if (codec_irq > 7)
			codec_irq += 0x68;
		else
			codec_irq += 0x08;

		_codec_data.old_codec_vec = gf1_getvect (codec_irq);
		gf1_setvect (codec_irq,codec_irq_handler);
		}
LEAVE_CRITICAL;
}

