// SCSI簡易Read/Writeキャッシュ

#include <scsi.h>
#include <stdlib.h>	// malloc/free
#include "ascsi.h"
#include "defines.h"

#define	DEBUG	0

int S_CacheOpen(S_CACHE_BUFF *scb,unlong id,long all,int mode)
// オープン(Read/Write共通)
// mode=S_CACHE_WRITE:Write , S_CACHE_READ:Read
{
struct READCAP cap; // 容量とブロック長
int ret;
	if (all<2||all>65535) return(5); // 確保ブロック数が少なすぎる/多すぎる
	
	// ドライブ情報取得
	ret=S_CheckReady(id);
	if (ret) return(ret);
	ret=S_READCAP(id,&cap);	// 容量情報取得
	if (ret) return(ret);
	scb->id=id;
	scb->sec1=cap.size;
	scb->blksz=(scb->sec1==2048? 3:scb->sec1/512); // S_WRITEEXT()のブロック長引数の算出
	
	// キャッシュ本体取得
	if ((scb->cache=malloc(all*scb->sec1))==NULL) {
		return(2);
	}
	#if DEBUG
	printf("cache=%p\n",scb->cache);
	#endif
	
	if (mode&S_CACHE_READ) {
		// キャッシュブロック毎構造体取得
		if ((scb->sectors=(S_CACHE1 *)malloc(all*sizeof(S_CACHE1)))==NULL) {
			return(3);
		}
		#if DEBUG
		printf("sectors構造体=%p\n",scb->sectors);
		#endif
	} // 書き込み時にオフセット表を使う時のsectors[]はユーザーが確保しておく
	
	scb->mode=mode;		// 動作モード記録
	scb->allblock=all;	// サイズ記録
	
	_S_CacheInit(scb); // 初期化
	return(0);
}

int S_CacheClose(S_CACHE_BUFF *scb)
// クローズ(Read/Write共通)
{
int ret;
	#if DEBUG
	printf("Close:");
	#endif
	switch (scb->mode&(S_CACHE_READ|S_CACHE_WRITE)) {
	case S_CACHE_WRITE:
		ret=S_CacheFlush(scb); // 残りがあれば書き出す
		//if (ret) return(ret);
		break;
	case S_CACHE_READ:
		free(scb->sectors);
		break;
	}
	// キャッシュ本体を解放（書き出しでエラーが発生してても）
	free(scb->cache);
	return(ret);
}
