/***************************************************************************
*	NAME:  IWL.H $Revision: 1.16 $
**	COPYRIGHT:
**	"Copyright (c) 1994,1995 by e-Tek Labs"
**
**       "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."
****************************************************************************
* $Log: iwl.h $
* Revision 1.16  1996/01/25 15:38:20  mleibow
* Revision 1.15  1995/10/27 16:19:58  sdsmith
* Changes for Wave compat tests in win95
* Revision 1.14  1995/10/26 12:00:28  mleibow
* Added command to allow removing of effects node from mixer when no memory on board.
* Revision 1.13  1995/10/13 17:23:17  mleibow
* Many changes for effects.c
* Revision 1.12  1995/06/20 08:55:34  sdsmith
* Added some definitions for other PnP registers
* Revision 1.11  1995/05/03 09:14:30  mleibow
* Changed MIDI defines to UART
* Revision 1.10  1995/04/19 17:15:42  sdsmith
* Added mixer init string max length
* Revision 1.9  1995/04/14 09:19:54  sdsmith
* Added support for B0 silicon
* Revision 1.8  1995/04/14 07:15:46  sdsmith
* Changed PNP register offsets for B0 silicon
* Revision 1.7  1995/04/10 11:24:44  mleibow
* Added ROM support
* Revision 1.6  1995/03/27 08:03:22  sdsmith
* Added iwl_mem_deinit prototype
* Revision 1.5  1995/03/27 07:53:25  sdsmith
* Removed old mixer node definition
* Revision 1.4  1995/03/24 09:44:14  mleibow
* Added initialization for MPU401 and other emulations
* Revision 1.3  1995/03/22 14:57:43  mleibow
* moved #include "codec.h" to iwl.h
* Revision 1.2  1995/02/24 14:21:00  mleibow
* added ALSB bit for UICI
* Revision 1.1  1995/02/23 11:07:09  unknown
* Initial revision
***************************************************************************/
#ifndef _IWL_H
#define _IWL_H

#include "config.h"
#include "os.h"
#include "iwlmacro.h"
#include "iwllist.h"

#define CARRY_FLAG	1

#define MIN_BASE	0x200
#define MAX_BASE	0x2f0

#define IWL_MIXER_INIT_MAX 256

/* INTERNAL FLAGS */
#define F_IW_OS_LOADED	  (1 << 0)
#define F_REDO_INT	  (1 << 1)
#define F_GEN_TC	  (1 << 2)
#define F_REDO_MIDI_INT   (1 << 3)
#define F_IW_NO_DMA	  (1 << 4)
#define F_IW_SYNTH_LOADED (1 << 5)
#define F_IW_CODEC_LOADED (1 << 6)

/* REGISTERS */
#define	SET_CONTROL		0x00
#define	SET_FREQUENCY		0x01
#define	SET_START_HIGH		0x02
#define	SET_START_LOW		0x03
#define	SET_END_HIGH		0x04
#define	SET_END_LOW		0x05
#define	SET_VOLUME_RATE		0x06
#define	SET_VOLUME_START	0x07
#define	SET_VOLUME_END		0x08
#define	SET_VOLUME		0x09
#define	SET_ACC_HIGH		0x0a
#define	SET_ACC_LOW		0x0b
#define	SET_BALANCE		0x0c
#define SET_RIGHT_OFFSET	0x0c
#define	SET_VOLUME_CONTROL 	0x0d
#define	SET_VOICES		0x0e
#define SET_UPPER_ADDR          0x10
#define SET_EFFECT_HIGH         0x11
#define SET_EFFECT_LOW          0x12
#define SET_LEFT_OFFSET	        0x13
#define SET_EFFECT_ACC_SEL      0x14
#define SET_VOICE_MODE          0x15
#define SET_EFFECT_VOLUME       0x16
#define SET_FREQ_LFO            0x17
#define SET_VOLUME_LFO          0x18
#define SET_GLOBAL_MODE         0x19
#define SET_LFO_BASE            0x1A
#define SET_RIGHT_FINAL_OFFSET  0x1B
#define SET_LEFT_FINAL_OFFSET   0x1C
#define SET_EFFECT_FINAL_VOLUME 0x1D
#define DMA_CONTROL             0x41
#define SET_DMA_ADDR_LOW	0x42
#define SET_DRAM_LOW            0x43
#define SET_DRAM_HIGH           0x44
#define ADLIB_CONTROL           0x45
#define ADLIB_TIMER1		0x46
#define ADLIB_TIMER2		0x47
#define	SET_SAMPLE_RATE		0x48  /* No longer used */
#define SAMPLE_CONTROL          0x49  /* No longer used */
#define SET_JOYSTICK		0x4B
#define MASTER_RESET		0x4C
#define SET_DMA_ADDR_HIGH       0x50
#define IW_LDSAHI               0x50
#define IW_LMSBAI               0x51
#define IW_LMCFI                0x52
#define IW_LMCI                 0x53
#define IW_LMRFAI               0x54
#define IW_LMPFAI               0x55
#define IW_LMFSI                0x56
#define IW_LDICI                0x57
#define IW_LDIBI                0x58
#define IW_ICMPTI               0x59
#define IW_IDECI                0x5a
#define IW_IVERI                0x5b
#define IW_IEMUAI               0x5c
#define IW_IEMUBI               0x5d
#define IW_GMRFAI               0x5e
#define IW_ITCI                 0x5f
#define IW_IEIRQI				0x60
#define	GET_CONTROL		0x80
#define	GET_FREQUENCY		0x81
#define	GET_START_HIGH		0x82
#define	GET_START_LOW		0x83
#define	GET_END_HIGH		0x84
#define	GET_END_LOW		0x85
#define	GET_VOLUME_RATE		0x86
#define	GET_VOLUME_START	0x87
#define	GET_VOLUME_END		0x88
#define	GET_VOLUME		0x89
#define	GET_ACC_HIGH		0x8a
#define	GET_ACC_LOW		0x8b
#define	GET_BALANCE		0x8c
#define	GET_VOLUME_CONTROL 	0x8d
#define	GET_VOICES		0x8e
#define	GET_IRQV		0x8f
#define GET_UPPER_ADDR          0x90
#define GET_EFFECT_HIGH         0x91
#define GET_EFFECT_LOW          0x92
#define GET_LEFT_OFFSET	        0x93
#define GET_EFFECT_ACC_SEL      0x94
#define GET_VOICE_MODE          0x95
#define GET_EFFECT_VOLUME       0x96
#define GET_FREQ_LFO            0x97
#define GET_VOLUME_LFO          0x98
#define GET_GLOBAL_MODE         0x99
#define GET_LFO_BASE            0x9A
#define GET_RIGHT_FINAL_OFFSET  0x9B
#define GET_LEFT_FINAL_OFFSET   0x9C
#define GET_EFFECT_FINAL_VOLUME 0x9D
#define GET_IRQV_NC             0x9F

/* Plug and Play Indirect Registers */
#define IW_PSRPAI 0x00
#define IW_PISOCI 0x01
#define IW_PCCCI  0x02
#define IW_PWAKEI 0x03
#define IW_PRESDI 0x04
#define IW_PRESSI 0x05
#define IW_PCSNI  0x06
#define IW_PLDNI  0x07
#define IW_PUACTI 0x30
#define IW_PURCI  0x31
#define IW_P2X0HI 0x60
#define IW_P2X0LI 0x61
#define IW_P3X0HI 0x62
#define IW_P3X0LI 0x63
#define IW_PHCAI  0x64
#define IW_PLCAI  0x65
#define IW_PRAHI  0x60
#define IW_PRALI  0x61
#define IW_PATAHI 0x60
#define IW_PATALI 0x61
#define IW_P201HI 0x60
#define IW_P201LI 0x61
#define IW_P388HI 0x60
#define IW_P388LI 0x61
#define IW_P401HI 0x60
#define IW_P401LI 0x61
#define IW_PUI1SI 0x70
#define IW_PUI2SI 0x72
#define IW_PUD1SI 0x74
#define IW_PUD2SI 0x75
#define IW_PSBISI 0x70
#define IW_PMISI  0x70
#define IW_PPWRI  0xF2

/* Plug and Play Logical Devices */
#define IWL_PNP_AUDIO  0
#define IWL_PNP_EXT    1
#define IWL_PNP_GAME   2
#define IWL_PNP_ADLIB  3
#define IWL_PNP_MPU401 4

/* REGISTER BITS */
/* mixer */
#define IWL_DISABLE_LINE	BIT0
#define IWL_DISABLE_OUT		BIT1
#define IWL_ENABLE_MIC		BIT2
#define IWL_ENABLE_IRQ_DMA	BIT3
#define IWL_UMCR_GF122		BIT4
#define IWL_SELECT_UICI         BIT6

/* decode control register */
#define IWL_IDECI_IAC22 	BIT7
#define IWL_IDECI_EICH1		BIT6
#define IWL_IDECI_EICH2		BIT5
#define IWL_IDECI_EINMI		BIT4
#define IWL_IDECI_ECOD		BIT3
#define IWL_IDECI_E3889		BIT2
#define IWL_IDECI_EEDC		BIT1
#define IWL_IDECI_EA98		BIT0

/* voice control */
#define IWL_STOPPED		BIT0
#define IWL_STOP		BIT1
#define IWL_WT16		BIT2
#define IWL_LPE			BIT3
#define IWL_BLE			BIT4
#define IWL_IRQE		BIT5
#define IWL_DIR_DEC		BIT6
#define IWL_IRQP		BIT7

/* volume control */
#define IWL_STOPPED		BIT0
#define IWL_STOP		BIT1
#define IWL_ENPCM		BIT2
#define IWL_LPE			BIT3
#define IWL_BLE			BIT4
#define IWL_IRQE		BIT5
#define IWL_DIR_DEC		BIT6
#define IWL_IRQP		BIT7

/* IRQ control */
#define IWL_COMBINE_IRQ		BIT6
#define IWL_ALSB		BIT7
 
/* DMA control */
#define IWL_COMBINE_DMA		BIT6

/* SGMI (synth global mode) */
#define IWL_SGMI_ENH		BIT0
#define IWL_SGMI_GLFOE		BIT1
#define IWL_SGMI_NOWVTBL	BIT2

/* LMCI (local memory control) */
#define IWL_LMCI_AI		BIT0
#define IWL_LMCI_ROMIO		BIT1

/* voice modes */
#define IWL_SMSI_ROM		BIT7
#define IWL_SMSI_ULAW		BIT6
#define IWL_SMSI_OFFEN		BIT5
#define IWL_SMSI_AEP		BIT4
#define IWL_SMSI_DAV		BIT1
#define IWL_SMSI_EPE		BIT0

/* register control register */
#define IWL_URCR_GP1IRQ		BIT3
#define IWL_URCR_GP2IRQ		BIT4
#define IWL_URCR_TG2XC		BIT5
#define IWL_URCR_EGPRA		BIT6
#define IWL_URCR_IQ2XE		BIT7

/* Emulation IRQ Register IEIRQI */
#define IWL_IEIRQI_IRQSB   BIT0
#define IWL_IEIRQI_IRQ401  BIT1
#define IWL_IEIRQI_SELGP   BIT7

/* LFO Control Bits */

/* Other */
#define IWL_ICMPTI_CPEN         BIT4
#define IWL_MPU401_MODE         BIT1

/* IRQ status register */
#define	UART_IRQ_SEND		BIT0
#define	UART_IRQ_RCV		BIT1
#define	TIMER_1			BIT2
#define	TIMER_2			BIT3
#define ADLIB_DATA		BIT4
#define	IWL_WAVETABLE		BIT5
#define	IWL_ENVELOPE		BIT6
#define	DMA_TC_BIT		BIT7

/* frequency of iwl clock */
#define CLOCK_RATE              9878400L

/* virtual centisecond timer */
#define MAX_CS_TIMERS (IW_MAX_VOICES+1)

/* Fletcher-Munson volume curve macros */
#define IWL_TO_FMM(x) ((1700UL*(unsigned long)x)>>10)
#define IWL_FROM_FMM(x) (((unsigned long)x<<10)/1700UL)

#define TIMER_ACTIVE 1
#define TIMER_STOP   2
struct timer_struct {
    struct iwl_node n;		/* node header, must be first in structure */
    USHORT cs_time;		/* countdown timer variable */
    void (*rtn)(USHORT data);	/* callback procedure */
    USHORT data;		/* data for callback procedure */
    UCHAR status;
};

/* internal data structures */
/* The data structure in Drams looks like this: */
/***************************************************************************

GLOBAL DEFINITION:
iwl_mem_block - internal structure to track DRAM usage

DESCRIPTION:
iwl_mem_block is a structure that is used to track the usage of
DRAM banks.  These data structures are normally kept in DRAM on the
card and are formed into a chain of free and used blocks.

Fields:
  size       - size of memory block not including block structure
  next_block - address of next DRAM memory block structure
  prev_block - address of previous DRAM memory block structure
  tag        
  status     - status of DRAM memory block
*/
struct iwl_mem_block {
	unsigned long size;
	unsigned long next_block;
	unsigned long prev_block;
	unsigned short tag;
	unsigned char status;
};

// LFO parameter block.  See AMD78C201 chip spec for more info
typedef struct iwl_lfo_param_s {
    unsigned short control;
    unsigned char  final_depth;
    unsigned char  depth_inc;
    unsigned long  unused;
    unsigned short twave_0;
    unsigned short depth_0;
    unsigned short twave_1;
    unsigned short depth_1;
} iwl_lfo_struct;

/* function prototypes for internal functions */
long iwl_convert_to_16bit(long address);
void iwl_enter(void);
void iwl_leave(void);
void iwl_set_irq(int);
void iwl_reset_irq(int);
void iwl_lfo_enable(int, unsigned char);
void iwl_lfo_disable(int, unsigned char);
void iwl_lfo_shutdown(int, unsigned char);
void iwl_lfo_change_freq(int, unsigned char, unsigned short frequency);
void iwl_lfo_change_final_depth(int, unsigned char, short);
void iwl_lfo_change_type( int, unsigned char, unsigned char);
void iwl_lfo_change_depth( int, unsigned char, short);
void iwl_lfo_change_ramp_time( int, unsigned char, short);
void iwl_lfo_setup(
  int voice,
  unsigned char lfo_type,
  unsigned short freq,
  unsigned short current_depth,
  short final_depth,
  short sweep,
  unsigned char shape);

void iwl_mute(int, int);
void iwl_process_irq1_interrupt(void);
void iwl_process_irq2_interrupt(void);
int iwl_get_pnp_config(void);
void iwl_isr_init(void);
void iwl_init_semaphores(void);
void iwl_write_block(unsigned long addr, struct iwl_mem_block RFAR *m);
void iwl_read_block(unsigned long addr, struct iwl_mem_block RFAR *m);
unsigned long iwl_steal_lfo_memory(void);
void iwl_init_ports(void);
long iwl_make_physical_address(unsigned short low, unsigned short high, unsigned short mode);
void iwl_set_addr_regs(int voice, unsigned long addr, int portl, int porth);
void iwl_set_addr_f_regs(
  int voice,
  unsigned long addr,
  int portl,
  int porth);
unsigned long iw_dma_buffer_xferred(unsigned long, int);
void iwl_lfo_write_block(int voice, unsigned char lfo_type, iwl_lfo_struct RFAR *lfo_block);
void iwl_stop_cs_timer(int tn);
void iwl_set_cs_timer(int tn, USHORT cs_time, void (*rtn)(USHORT data), USHORT data);
void iwl_mixer_remove_effects_node(void);

#ifdef OS2
void RFAR iwl_irq1_service(void);
void RFAR iwl_irq2_service(void);
#else
OS_INTERRUPT iwl_irq1_service;
OS_INTERRUPT iwl_irq2_service;
#endif

/* INITIALIZATION ROUTINES */
int iwl_timer_init(void);
int iwl_mem_init(void);
int iwl_voice_init(void);
int iwl_dma_init(void);
int iwl_lfo_init(void);
int iwl_uart_init(void);
int iwl_record_init(void);
int iwl_codec_init(void);
int iwl_note_init(void);
int iwl_sound_init(void);
void iwl_mem_deinit(void);
int iwl_effects_init(struct load_kernel_cfg RFAR *cfg);
int iwl_synth_dig_init(void);
void iwl_synth_dig_deinit(void);
void iwl_dma_deinit(void);
void iwl_timer_deinit(void);
void iwl_note_deinit(void);

/* INTERNAL macros */
/* interrupt semaphores ENTER and LEAVE */
#define ENTER { OS_PUSH_DISABLE(); iwl_enter(); }

#define LEAVE { iwl_leave(); OS_POP_FLAGS(); }

#endif
