/*
 * $Id: dmamgr.h,v 1.1.1.1 2003/05/19 20:32:47 tong Exp $
 * $Log: dmamgr.h,v $
 * Revision 1.1.1.1  2003/05/19 20:32:47  tong
 * Yoshi's Story orig. tree from Nintendo
 *
 * Revision 1.9  1998/04/01  02:42:32  hayakawa
 * 汎用性を考え __cplusplus を _LANGUAGE_C_PLUS_PLUS に変更
 *
 * Revision 1.8  1997/11/21  02:12:23  hayakawa
 * *** empty log message ***
 *
 * Revision 1.7  1997/01/10  09:18:20  hayakawa
 * マクロを追加
 *
 * Revision 1.6  1996/11/26  05:50:21  hayakawa
 * header.hをはずし、個別にインクルードするようにした
 *
 */

#ifndef __DMAMGR_H_
#define __DMAMGR_H_

#include "ultra64.h"		/* n64基本ヘッダ */
#include "bg_config.h"

#ifdef _LANGUAGE_C_PLUS_PLUS
extern "C" {
#endif
    
#define DMAMGR_MAGIC 'CMPR'
#define DMAMGR_HEADER_SIZE (16)

typedef struct head_s {
    u32 magic;
    u32 compsize;
    u32 origsize;
    u32 dummy;
} head_t;

typedef struct dma_s {
    u32		romadr;		/* ROMアドレス */
    void	*dstptr;	/* dmadst==NULLの時はヘッダ転送先 */
    u32		dstsiz;		/* データ格納領域サイズ */
    void	*appwork;	/* 圧縮データ時のワーク領域 */
    u8		headread;
    u8		compressed;
    u32		dmarom;		/* ROMアドレス */
    void	*dmadst;	/* NULLの時はヘッダ読み込み */
    u32		dmasiz;		/* ＤＭＡ転送サイズ */
    OSIoMesg	iom;
    s32		pri;
    OSMesgQueue	*mq;
    OSMesg	m;
#if DEBUG
    OSTime	start_time;
    OSTime	end_time;
    OSTime	mid_time;
#endif
} dma_t;

void CreateDmaManager( void );
void dmacopy_fg(
    void *dst,			/* 転送先ＲＡＭアドレス（８バイトバウンダリ） */
    u32 src,			/* 転送元ＲＯＭアドレス（２バイトバウンダリ） */
    u32 size			/* 転送バイト数 */
);

void
dmacopy_bg(
    dma_t *dmap,		/* ＤＭＡワーク（転送完了するまで必要） */
    void *dst,			/* 転送先ＲＡＭアドレス（８バイトバウンダリ） */
    u32 src,			/* 転送元ＲＯＭアドレス（２バイトバウンダリ） */
    u32 size,			/* 転送バイト数 */
    void *work,			/* 圧縮データの場合に使う作業領域の先頭 */
    OSMesgQueue *mq,		/* 転送完了時にメッセージを送るキュー  */
				/* NULLなら送らない */
    OSMesg m			/* 転送完了メッセージ */
);

/*
 * ＤＭＡ転送関連マクロ
 */

/*
 * ＲＯＭからＤＲＡＭにＤＭＡ転送する（基本版）
 */


#if DEBUG
#define DMACOPY_DISP(k0_addr, rom_addr, siz) \
    PRINTF("DMA転送 ROM=%08x, SIZE=%08x, RAM=%08x-%08x\n", \
	   (u32)(rom_addr), (siz), \
	   (void *)(k0_addr), (char *)(k0_addr) + (siz) - 1)
#define DMACOPY_SEGMENT_DISP(addr, name) \
    do { \
EXTERN_DEFSEG_RAW(name); \
PRINTF("DMA転送 ROM=%08x, SIZE=%08x, PHY=%08x-%08x, [%s]\n", \
       (u32)(_##name##SegmentRomStart), SEGMENT_ROM_SIZE(name), \
       (void *)(addr), \
       (char *)(addr) + (SEGMENT_ROM_SIZE(name) - 1), #name); \
} while (0)

#else
#define DMACOPY_DISP(k0_addr, rom_addr, siz) ((void)0)
#define DMACOPY_SEGMENT_DISP(addr, name) ((void)0)
#endif
    
/*
 * ＲＯＭからＤＲＡＭにＤＭＡ転送する（アドレス、サイズ指定）
 */
#define DMACOPY(k0_addr, rom_addr, siz) \
    dmacopy_fg(k0_addr, rom_addr, siz)
#define DMACOPY_WAIT() {int DMACOPY_WAIT;}/* ワーニングを発生させる */
#define DMACOPY_SEGMENT(addr, name) \
    do { \
	EXTERN_DEFSEG_RAW(name); \
	dmacopy_fg((void *)(addr), \
		   (u32)(_##name##SegmentRomStart), SEGMENT_ROM_SIZE(name)); \
    } while (0)
#define DMACOPY_SEGMENT(addr, name) \
    do { \
	EXTERN_DEFSEG_RAW(name); \
	dmacopy_fg((void *)(addr), \
		   (u32)(_##name##SegmentRomStart), SEGMENT_ROM_SIZE(name)); \
    } while (0)
    
/*
 * ＲＯＭからＤＲＡＭにＤＭＡ転送する（１テーブル）
 */
#define DMACOPY_TABLE(addr, table) \
    DMACOPY(addr, SEGMENT_TO_ROM(table), sizeof(table))

#ifdef _LANGUAGE_C_PLUS_PLUS
} /* extern "C" */
#endif

#endif /* __DMAMGR_H_ */
