/*
 * $Id: dmamgr.h,v 1.1 2003/02/07 18:15:44 wheeler Exp $
 * $Log: dmamgr.h,v $
 * Revision 1.1  2003/02/07 18:15:44  wheeler
 * Fox's version of libultra and friends.
 *
 * 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基本ヘッダ */

#ifdef __cplusplus
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 __cplusplus
} /* extern "C" */
#endif

#endif /* __DMAMGR_H_ */
