/*     
 **********************************************************************
 *     sblive_mi.h
 *     Copyright 1999, 2000 Creative Labs, Inc. 
 * 
 ********************************************************************** 
 * 
 *     Date                 Author          Summary of changes 
 *     ----                 ------          ------------------ 
 *     October 20, 1999     Bertrand Lee    base code release 
 *     November 2, 1999     Alan Cox        cleaned up
 * 
 ********************************************************************** 
 * 
 *     This program is free software; you can redistribute it and/or 
 *     modify it under the terms of the GNU General Public License as 
 *     published by the Free Software Foundation; either version 2 of 
 *     the License, or (at your option) any later version. 
 * 
 *     This program is distributed in the hope that it will be useful, 
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 *     GNU General Public License for more details. 
 * 
 *     You should have received a copy of the GNU General Public 
 *     License along with this program; if not, write to the Free 
 *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 
 *     USA. 
 * 
 ********************************************************************** 
 */ 

#ifndef _CARDMI_H
#define _CARDMI_H

#include "icardmid.h"

typedef enum
{
    STIN_PARSE = 0,
    STIN_3BYTE,                     /* 0x80, 0x90, 0xA0, 0xB0, 0xE0 */
    STIN_3BYTE_KEY,                 /* Byte 1 */
    STIN_3BYTE_VEL,                 /* Byte 1 */
    STIN_2BYTE,                     /* 0xC0, 0xD0 */
    STIN_2BYTE_KEY,                 /* Byte 1 */
    STIN_SYS_COMMON_2,              /* 0xF1, 0xF3  */
    STIN_SYS_COMMON_2_KEY,
    STIN_SYS_COMMON_3,              /* 0xF2 */
    STIN_SYS_COMMON_3_KEY,
    STIN_SYS_COMMON_3_VEL,
    STIN_SYS_EX_NORM,               /* 0xF0, Normal mode */
    STIN_SYS_REAL
} midi_in_state;


/* flags for card MIDI in object */
#define FLAGS_MIDM_STARTED          0x00001000      // Data has started to come in after Midm Start
#define MIDIIN_MAX_BUFFER_SIZE      200             // Definition for struct sblive_mpuin

struct midi_data
{
    u8 data;
    u32 timein;
};

struct sblive_mpuin
{
    spinlock_t        lock;
    struct midi_queue *firstmidiq;
    struct midi_queue *lastmidiq;
    unsigned          qhead, qtail;
    struct midi_data  midiq[MIDIIN_MAX_BUFFER_SIZE];
    CTDPC             dpc;
    struct midi_openinfo    openinfo;
    struct midi_caps        caps;

    /* For MIDI state machine */
    u8              status;        /* For MIDI running status */
    u8              fstatus;       /* For 0xFn status only */
    midi_in_state   curstate;
    midi_in_state   laststate;
    u32             timestart;
    u32             timein;
    u8              data;
};

int sblive_mpuinInit(struct sblive_mpuin *, struct sblive_hw *);
int sblive_mpuinExit(struct sblive_hw *);

int sblive_mpuinGetCaps          (struct sblive_mpuin *, struct midi_caps *);
int sblive_mpuinOpen             (struct sblive_hw *, struct midi_openinfo *, u32 *);
int sblive_mpuinClose            (struct sblive_hw *, u32);
int sblive_mpuinAddBuffer        (struct sblive_mpuin *, u32, struct midi_hdr *);
int sblive_mpuinStart            (struct sblive_hw *, u32);
int sblive_mpuinStop             (struct sblive_hw *, u32);
int sblive_mpuinWriteShortData   (struct sblive_mpuin *, u32, u32);
int sblive_mpuinPause            (struct sblive_mpuin *, u32);
int sblive_mpuinStream           (struct sblive_mpuin *, u32, struct midi_hdr *);
int sblive_mpuinRestart          (struct sblive_mpuin *, u32);
int sblive_mpuinReset            (struct sblive_hw *, u32);
int sblive_mpuinCache            (struct sblive_mpuin *, u32, struct midi_cache *);
int sblive_mpuinGetPosition      (struct sblive_mpuin *, u32, u32 *);
int sblive_mpuinGetControl       (struct sblive_mpuin *, u32, u32, u32 *);
int sblive_mpuinSetControl       (struct sblive_mpuin *, u32, u32, u32 *);

#define IDS_EMU_MIDIIN_PNAME                "SB Live! In"

int sblive_miStateInit(struct sblive_mpuin *);
int sblive_miStateEntry(struct sblive_mpuin *, u8);
int sblive_miStateParse(struct sblive_mpuin *, u8);
int sblive_miState3Byte(struct sblive_mpuin *, u8);
int sblive_miState3ByteKey(struct sblive_mpuin *, u8);
int sblive_miState3ByteVel(struct sblive_mpuin *, u8);
int sblive_miState2Byte(struct sblive_mpuin *, u8);
int sblive_miState2ByteKey(struct sblive_mpuin *, u8);
int sblive_miStateSysCommon2(struct sblive_mpuin *, u8);
int sblive_miStateSysCommon2Key(struct sblive_mpuin *, u8);
int sblive_miStateSysCommon3(struct sblive_mpuin *, u8);
int sblive_miStateSysCommon3Key(struct sblive_mpuin *, u8);
int sblive_miStateSysCommon3Vel(struct sblive_mpuin *, u8);
int sblive_miStateSysExNorm(struct sblive_mpuin *, u8);
int sblive_miStateSysReal(struct sblive_mpuin *, u8);

static struct 
{
	int (*Fn) (struct sblive_mpuin * card_mpuin, u8 data);
} midistatefn[] =
{
	{ sblive_miStateParse },
	{ sblive_miState3Byte }, 	/* 0x8n, 0x9n, 0xAn, 0xBn, 0xEn */
	{ sblive_miState3ByteKey },    	/* Byte 1                       */
	{ sblive_miState3ByteVel },    	/* Byte 2                       */
	{ sblive_miState2Byte },       	/* 0xCn, 0xDn                   */
	{ sblive_miState2ByteKey },    	/* Byte 1                       */
	{ sblive_miStateSysCommon2 },	/* 0xF1 , 0xF3                  */
	{ sblive_miStateSysCommon2Key },/* 0xF1 , 0xF3, Byte 1          */
	{ sblive_miStateSysCommon3 },  	/* 0xF2                         */
	{ sblive_miStateSysCommon3Key },/* 0xF2 , Byte 1                */
	{ sblive_miStateSysCommon3Vel },/* 0xF2 , Byte 2                */
	{ sblive_miStateSysExNorm },	/* 0xF0, 0xF7, Normal mode      */
	{ sblive_miStateSysReal }	/* 0xF4 - 0xF6 ,0xF8 - 0xFF     */
};

int sblive_mpuinIrqCallback(unsigned long event, unsigned long refdata, unsigned long param);
int sblive_mpuinDpcCallback(unsigned long event, unsigned long refdata, unsigned long param);
int sblive_mpuinMidiCallback(struct sblive_mpuin *card_mpuin, u32 msg, u32 data, u32 bytesvalid);

#endif  /* _CARDMI_H */

