Files
RASCSI/src/x68k/RASDRV/BRIDGE.C
Xavier Rey-Robert 35866cfb84 first commit
2018-05-03 15:47:57 +02:00

2415 lines
51 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Powered by XM6 TypeG Technorogy.
// Copyright (C) 2016-2017 GIMONS
// [ ホストファイルシステム ブリッジドライバ ]
//
//---------------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include <sys/dos.h>
#include <sys/scsi.h>
#include <iocslib.h>
#include "bridge.h"
//---------------------------------------------------------------------------
//
// 変数宣言
//
//---------------------------------------------------------------------------
volatile BYTE *request; // リクエストヘッダアドレス
DWORD command; // コマンド番号
DWORD unit; // ユニット番号
//===========================================================================
//
/// ファイルシステム(SCSI連携)
//
//===========================================================================
typedef struct
{
char DeviceType;
char RMB;
char ANSI_Ver;
char RDF;
char AddLen;
char RESV0;
char RESV1;
char OptFunc;
char VendorID[8];
char ProductID[16];
char FirmRev[4];
} INQUIRY_T;
int scsiid; // SCSI ID
//---------------------------------------------------------------------------
//
// 初期化
//
//---------------------------------------------------------------------------
BOOL SCSI_Init(void)
{
int i;
INQUIRY_T inq;
// SCSI ID未定
scsiid = -1;
for (i = 0; i <= 7; i++) {
if (S_INQUIRY(sizeof(INQUIRY_T) , i, (struct INQUIRY*)&inq) < 0) {
continue;
}
if (memcmp(&(inq.ProductID), "RASCSI BRIDGE", 13) != 0) {
continue;
}
// SCSI ID確定
scsiid = i;
return TRUE;
}
return FALSE;
}
//---------------------------------------------------------------------------
//
// コマンド送信
//
//---------------------------------------------------------------------------
int SCSI_SendCmd(BYTE *buf, int len)
{
int ret;
BYTE cmdbuf[10];
BYTE sts;
BYTE msg;
BYTE retbuf[4];
ret = FS_FATAL_MEDIAOFFLINE;
cmdbuf[0] = 0x2a;
cmdbuf[1] = 0;
cmdbuf[2] = 2;
cmdbuf[3] = command;
cmdbuf[4] = 0;
cmdbuf[5] = 0;
cmdbuf[6] = (BYTE)(len >> 16);
cmdbuf[7] = (BYTE)(len >> 8);
cmdbuf[8] = (BYTE)len;
cmdbuf[9] = 0;
// セレクトがタイムアウトする時には再試行
if (S_SELECT(scsiid) != 0) {
S_RESET();
if (S_SELECT(scsiid) != 0) {
return ret;
}
}
if (S_CMDOUT(10, cmdbuf) != 0) {
return ret;
}
if (S_DATAOUT_P(len, buf) != 0) {
return ret;
}
if (S_STSIN(&sts) != 0) {
return ret;
}
if (S_MSGIN(&msg) != 0) {
return ret;
}
cmdbuf[0] = 0x28;
cmdbuf[1] = 0;
cmdbuf[2] = 2;
cmdbuf[3] = command;
cmdbuf[4] = 0;
cmdbuf[5] = 0;
cmdbuf[6] = 0;
cmdbuf[7] = 0;
cmdbuf[8] = 4;
cmdbuf[9] = 0;
// セレクトがタイムアウトする時には再試行
if (S_SELECT(scsiid) != 0) {
S_RESET();
if (S_SELECT(scsiid) != 0) {
return ret;
}
}
if (S_CMDOUT(10, cmdbuf) != 0) {
return ret;
}
if (S_DATAIN_P(4, retbuf) != 0) {
return ret;
}
if (S_STSIN(&sts) != 0) {
return ret;
}
if (S_MSGIN(&msg) != 0) {
return ret;
}
ret = *(int*)retbuf;
return ret;
}
//---------------------------------------------------------------------------
//
// コマンド呼び出し
//
//---------------------------------------------------------------------------
int SCSI_CalCmd(BYTE *buf, int len, BYTE *outbuf, int outlen)
{
int ret;
BYTE cmdbuf[10];
BYTE sts;
BYTE msg;
BYTE retbuf[4];
ret = FS_FATAL_MEDIAOFFLINE;
cmdbuf[0] = 0x2a;
cmdbuf[1] = 0;
cmdbuf[2] = 2;
cmdbuf[3] = command;
cmdbuf[4] = 0;
cmdbuf[5] = 0;
cmdbuf[6] = (BYTE)(len >> 16);
cmdbuf[7] = (BYTE)(len >> 8);
cmdbuf[8] = (BYTE)len;
cmdbuf[9] = 0;
// セレクトがタイムアウトする時には再試行
if (S_SELECT(scsiid) != 0) {
S_RESET();
if (S_SELECT(scsiid) != 0) {
return ret;
}
}
if (S_CMDOUT(10, cmdbuf) != 0) {
return ret;
}
if (S_DATAOUT_P(len, buf) != 0) {
return ret;
}
if (S_STSIN(&sts) != 0) {
return ret;
}
if (S_MSGIN(&msg) != 0) {
return ret;
}
cmdbuf[0] = 0x28;
cmdbuf[1] = 0;
cmdbuf[2] = 2;
cmdbuf[3] = command;
cmdbuf[4] = 0;
cmdbuf[5] = 0;
cmdbuf[6] = 0;
cmdbuf[7] = 0;
cmdbuf[8] = 4;
cmdbuf[9] = 0;
// セレクトがタイムアウトする時には再試行
if (S_SELECT(scsiid) != 0) {
S_RESET();
if (S_SELECT(scsiid) != 0) {
return ret;
}
}
if (S_CMDOUT(10, cmdbuf) != 0) {
return ret;
}
if (S_DATAIN_P(4, retbuf) != 0) {
return ret;
}
if (S_STSIN(&sts) != 0) {
return ret;
}
if (S_MSGIN(&msg) != 0) {
return ret;
}
// エラーなら返却データの受信を止める
ret = *(int*)retbuf;
if (ret < 0) {
return ret;
}
cmdbuf[0] = 0x28;
cmdbuf[1] = 0;
cmdbuf[2] = 2;
cmdbuf[3] = command;
cmdbuf[4] = 0;
cmdbuf[5] = 0;
cmdbuf[6] = (BYTE)(outlen >> 16);
cmdbuf[7] = (BYTE)(outlen >> 8);
cmdbuf[8] = (BYTE)outlen;
cmdbuf[9] = 1;
// セレクトがタイムアウトする時には再試行
if (S_SELECT(scsiid) != 0) {
S_RESET();
if (S_SELECT(scsiid) != 0) {
return ret;
}
}
if (S_CMDOUT(10, cmdbuf) != 0) {
return ret;
}
if (S_DATAIN_P(outlen, outbuf) != 0) {
return ret;
}
if (S_STSIN(&sts) != 0) {
return ret;
}
if (S_MSGIN(&msg) != 0) {
return ret;
}
ret = *(int*)retbuf;
return ret;
}
//---------------------------------------------------------------------------
//
// オプションデータ取得
//
//---------------------------------------------------------------------------
BOOL SCSI_ReadOpt(BYTE *buf, int len)
{
BYTE cmdbuf[10];
BYTE sts;
BYTE msg;
cmdbuf[0] = 0x28;
cmdbuf[1] = 0;
cmdbuf[2] = 2;
cmdbuf[3] = command;
cmdbuf[4] = 0;
cmdbuf[5] = 0;
cmdbuf[6] = (BYTE)(len >> 16);
cmdbuf[7] = (BYTE)(len >> 8);
cmdbuf[8] = (BYTE)len;
cmdbuf[9] = 2;
// セレクトがタイムアウトする時には再試行
if (S_SELECT(scsiid) != 0) {
S_RESET();
if (S_SELECT(scsiid) != 0) {
return FALSE;
}
}
if (S_CMDOUT(10, cmdbuf) != 0) {
return FALSE;
}
if (S_DATAIN_P(len, buf) != 0) {
return FALSE;
}
if (S_STSIN(&sts) != 0) {
return FALSE;
}
if (S_MSGIN(&msg) != 0) {
return FALSE;
}
return TRUE;
}
//---------------------------------------------------------------------------
//
// オプションデータ書き込み
//
//---------------------------------------------------------------------------
BOOL SCSI_WriteOpt(BYTE *buf, int len)
{
BYTE cmdbuf[10];
BYTE sts;
BYTE msg;
cmdbuf[0] = 0x2a;
cmdbuf[1] = 0;
cmdbuf[2] = 2;
cmdbuf[3] = command;
cmdbuf[4] = 0;
cmdbuf[5] = 0;
cmdbuf[6] = (BYTE)(len >> 16);
cmdbuf[7] = (BYTE)(len >> 8);
cmdbuf[8] = (BYTE)len;
cmdbuf[9] = 1;
// セレクトがタイムアウトする時には再試行
if (S_SELECT(scsiid) != 0) {
S_RESET();
if (S_SELECT(scsiid) != 0) {
return FALSE;
}
}
if (S_CMDOUT(10, cmdbuf) != 0) {
return FALSE;
}
if (S_DATAOUT_P(len, buf) != 0) {
return FALSE;
}
if (S_STSIN(&sts) != 0) {
return FALSE;
}
if (S_MSGIN(&msg) != 0) {
return FALSE;
}
return TRUE;
}
//===========================================================================
//
/// ファイルシステム
//
//===========================================================================
//---------------------------------------------------------------------------
//
// $40 - デバイス起動
//
//---------------------------------------------------------------------------
DWORD FS_InitDevice(const argument_t* pArgument)
{
return (DWORD)SCSI_SendCmd((BYTE*)pArgument, sizeof(argument_t));
}
//---------------------------------------------------------------------------
//
// $41 - ディレクトリチェック
//
//---------------------------------------------------------------------------
int FS_CheckDir(const namests_t* pNamests)
{
BYTE buf[256];
DWORD *dp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = unit;
i += sizeof(DWORD);
memcpy(&buf[i], pNamests, sizeof(namests_t));
i += sizeof(namests_t);
return SCSI_SendCmd(buf, i);
}
//---------------------------------------------------------------------------
//
// $42 - ディレクトリ作成
//
//---------------------------------------------------------------------------
int FS_MakeDir(const namests_t* pNamests)
{
BYTE buf[256];
DWORD *dp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = unit;
i += sizeof(DWORD);
memcpy(&buf[i], pNamests, sizeof(namests_t));
i += sizeof(namests_t);
return SCSI_SendCmd(buf, i);
}
//---------------------------------------------------------------------------
//
// $43 - ディレクトリ削除
//
//---------------------------------------------------------------------------
int FS_RemoveDir(const namests_t* pNamests)
{
BYTE buf[256];
DWORD *dp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = unit;
i += sizeof(DWORD);
memcpy(&buf[i], pNamests, sizeof(namests_t));
i += sizeof(namests_t);
return SCSI_SendCmd(buf, i);
}
//---------------------------------------------------------------------------
//
// $44 - ファイル名変更
//
//---------------------------------------------------------------------------
int FS_Rename(const namests_t* pNamests, const namests_t* pNamestsNew)
{
BYTE buf[256];
DWORD *dp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = unit;
i += sizeof(DWORD);
memcpy(&buf[i], pNamests, sizeof(namests_t));
i += sizeof(namests_t);
memcpy(&buf[i], pNamestsNew, sizeof(namests_t));
i += sizeof(namests_t);
return SCSI_SendCmd(buf, i);
}
//---------------------------------------------------------------------------
//
// $45 - ファイル削除
//
//---------------------------------------------------------------------------
int FS_Delete(const namests_t* pNamests)
{
BYTE buf[256];
DWORD *dp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = unit;
i += sizeof(DWORD);
memcpy(&buf[i], pNamests, sizeof(namests_t));
i += sizeof(namests_t);
return SCSI_SendCmd(buf, i);
}
//---------------------------------------------------------------------------
//
// $46 - ファイル属性取得/設定
//
//---------------------------------------------------------------------------
int FS_Attribute(const namests_t* pNamests, DWORD nHumanAttribute)
{
BYTE buf[256];
DWORD *dp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = unit;
i += sizeof(DWORD);
memcpy(&buf[i], pNamests, sizeof(namests_t));
i += sizeof(namests_t);
dp = (DWORD*)&buf[i];
*dp = nHumanAttribute;
i += sizeof(DWORD);
return SCSI_SendCmd(buf, i);
}
//---------------------------------------------------------------------------
//
// $47 - ファイル検索
//
//---------------------------------------------------------------------------
int FS_Files(DWORD nKey,
const namests_t* pNamests, files_t* info)
{
BYTE buf[256];
DWORD *dp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = unit;
i += sizeof(DWORD);
dp = (DWORD*)&buf[i];
*dp = nKey;
i += sizeof(DWORD);
memcpy(&buf[i], pNamests, sizeof(namests_t));
i += sizeof(namests_t);
memcpy(&buf[i], info, sizeof(files_t));
i += sizeof(files_t);
return SCSI_CalCmd(buf, i, (BYTE*)info, sizeof(files_t));
}
//---------------------------------------------------------------------------
//
// $48 - ファイル次検索
//
//---------------------------------------------------------------------------
int FS_NFiles(DWORD nKey, files_t* info)
{
BYTE buf[256];
DWORD *dp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = unit;
i += sizeof(DWORD);
dp = (DWORD*)&buf[i];
*dp = nKey;
i += sizeof(DWORD);
memcpy(&buf[i], info, sizeof(files_t));
i += sizeof(files_t);
return SCSI_CalCmd(buf, i, (BYTE*)info, sizeof(files_t));
}
//---------------------------------------------------------------------------
//
// $49 - ファイル作成
//
//---------------------------------------------------------------------------
int FS_Create(DWORD nKey,
const namests_t* pNamests, fcb_t* pFcb, DWORD nAttribute, BOOL bForce)
{
BYTE buf[256];
DWORD *dp;
BOOL *bp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = unit;
i += sizeof(DWORD);
dp = (DWORD*)&buf[i];
*dp = nKey;
i += sizeof(DWORD);
memcpy(&buf[i], pNamests, sizeof(namests_t));
i += sizeof(namests_t);
memcpy(&buf[i], pFcb, sizeof(fcb_t));
i += sizeof(fcb_t);
dp = (DWORD*)&buf[i];
*dp = nAttribute;
i += sizeof(DWORD);
bp = (BOOL*)&buf[i];
*bp = bForce;
i += sizeof(BOOL);
return SCSI_CalCmd(buf, i, (BYTE*)pFcb, sizeof(fcb_t));
}
//---------------------------------------------------------------------------
//
// $4A - ファイルオープン
//
//---------------------------------------------------------------------------
int FS_Open(DWORD nKey,
const namests_t* pNamests, fcb_t* pFcb)
{
BYTE buf[256];
DWORD *dp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = unit;
i += sizeof(DWORD);
dp = (DWORD*)&buf[i];
*dp = nKey;
i += sizeof(DWORD);
memcpy(&buf[i], pNamests, sizeof(namests_t));
i += sizeof(namests_t);
memcpy(&buf[i], pFcb, sizeof(fcb_t));
i += sizeof(fcb_t);
return SCSI_CalCmd(buf, i, (BYTE*)pFcb, sizeof(fcb_t));
}
//---------------------------------------------------------------------------
//
// $4B - ファイルクローズ
//
//---------------------------------------------------------------------------
int FS_Close(DWORD nKey, fcb_t* pFcb)
{
BYTE buf[256];
DWORD *dp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = unit;
i += sizeof(DWORD);
dp = (DWORD*)&buf[i];
*dp = nKey;
i += sizeof(DWORD);
memcpy(&buf[i], pFcb, sizeof(fcb_t));
i += sizeof(fcb_t);
return SCSI_CalCmd(buf, i, (BYTE*)pFcb, sizeof(fcb_t));
}
//---------------------------------------------------------------------------
//
// $4C - ファイル読み込み
//
//---------------------------------------------------------------------------
int FS_Read(DWORD nKey, fcb_t* pFcb, BYTE* pAddress, DWORD nSize)
{
BYTE buf[256];
DWORD *dp;
int i;
int nResult;
i = 0;
dp = (DWORD*)buf;
*dp = nKey;
i += sizeof(DWORD);
memcpy(&buf[i], pFcb, sizeof(fcb_t));
i += sizeof(fcb_t);
dp = (DWORD*)&buf[i];
*dp = nSize;
i += sizeof(DWORD);
nResult = SCSI_CalCmd(buf, i, (BYTE*)pFcb, sizeof(fcb_t));
if (nResult > 0) {
SCSI_ReadOpt(pAddress, nResult);
}
return nResult;
}
//---------------------------------------------------------------------------
//
// $4D - ファイル書き込み
//
//---------------------------------------------------------------------------
int FS_Write(DWORD nKey, fcb_t* pFcb, BYTE* pAddress, DWORD nSize)
{
BYTE buf[256];
DWORD *dp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = nKey;
i += sizeof(DWORD);
memcpy(&buf[i], pFcb, sizeof(fcb_t));
i += sizeof(fcb_t);
dp = (DWORD*)&buf[i];
*dp = nSize;
i += sizeof(DWORD);
if (nSize != 0) {
if (!SCSI_WriteOpt(pAddress, nSize)) {
return FS_FATAL_MEDIAOFFLINE;
}
}
return SCSI_SendCmd(buf, i);
}
//---------------------------------------------------------------------------
//
// $4E - ファイルシーク
//
//---------------------------------------------------------------------------
int FS_Seek(DWORD nKey, fcb_t* pFcb, DWORD nMode, int nOffset)
{
BYTE buf[256];
DWORD *dp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = nKey;
i += sizeof(DWORD);
memcpy(&buf[i], pFcb, sizeof(fcb_t));
i += sizeof(fcb_t);
dp = (DWORD*)&buf[i];
*dp = nMode;
i += sizeof(DWORD);
dp = (DWORD*)&buf[i];
*dp = nOffset;
i += sizeof(int);
return SCSI_CalCmd(buf, i, (BYTE*)pFcb, sizeof(fcb_t));
}
//---------------------------------------------------------------------------
//
// $4F - ファイル時刻取得/設定
//
//---------------------------------------------------------------------------
DWORD FS_TimeStamp(DWORD nKey,
fcb_t* pFcb, DWORD nHumanTime)
{
BYTE buf[256];
DWORD *dp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = unit;
i += sizeof(DWORD);
dp = (DWORD*)&buf[i];
*dp = nKey;
i += sizeof(DWORD);
memcpy(&buf[i], pFcb, sizeof(fcb_t));
i += sizeof(fcb_t);
dp = (DWORD*)&buf[i];
*dp = nHumanTime;
i += sizeof(DWORD);
return (DWORD)SCSI_CalCmd(buf, i, (BYTE*)pFcb, sizeof(fcb_t));
}
//---------------------------------------------------------------------------
//
// $50 - 容量取得
//
//---------------------------------------------------------------------------
int FS_GetCapacity(capacity_t* cap)
{
BYTE buf[256];
DWORD *dp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = unit;
i += sizeof(DWORD);
return SCSI_CalCmd(buf, i, (BYTE*)cap, sizeof(capacity_t));
}
//---------------------------------------------------------------------------
//
// $51 - ドライブ状態検査/制御
//
//---------------------------------------------------------------------------
int FS_CtrlDrive(ctrldrive_t* pCtrlDrive)
{
BYTE buf[256];
DWORD *dp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = unit;
i += sizeof(DWORD);
memcpy(&buf[i], pCtrlDrive, sizeof(ctrldrive_t));
i += sizeof(ctrldrive_t);
return SCSI_CalCmd(buf, i, (BYTE*)pCtrlDrive, sizeof(ctrldrive_t));
}
//---------------------------------------------------------------------------
//
// $52 - DPB取得
//
//---------------------------------------------------------------------------
int FS_GetDPB(dpb_t* pDpb)
{
BYTE buf[256];
DWORD *dp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = unit;
i += sizeof(DWORD);
return SCSI_CalCmd(buf, i, (BYTE*)pDpb, sizeof(dpb_t));
}
//---------------------------------------------------------------------------
//
// $53 - セクタ読み込み
//
//---------------------------------------------------------------------------
int FS_DiskRead(BYTE* pBuffer, DWORD nSector, DWORD nSize)
{
BYTE buf[256];
DWORD *dp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = unit;
i += sizeof(DWORD);
dp = (DWORD*)&buf[i];
*dp = nSector;
i += sizeof(DWORD);
dp = (DWORD*)&buf[i];
*dp = nSize;
i += sizeof(DWORD);
return SCSI_CalCmd(buf, i, (BYTE*)pBuffer, 0x200);
}
//---------------------------------------------------------------------------
//
// $54 - セクタ書き込み
//
//---------------------------------------------------------------------------
int FS_DiskWrite()
{
BYTE buf[256];
DWORD *dp;
dp = (DWORD*)buf;
*dp = unit;
return SCSI_SendCmd(buf, 4);
}
//---------------------------------------------------------------------------
//
// $55 - IOCTRL
//
//---------------------------------------------------------------------------
int FS_Ioctrl(DWORD nFunction, ioctrl_t* pIoctrl)
{
BYTE buf[256];
DWORD *dp;
int i;
i = 0;
dp = (DWORD*)buf;
*dp = unit;
i += sizeof(DWORD);
dp = (DWORD*)&buf[i];
*dp = nFunction;
i += sizeof(DWORD);
memcpy(&buf[i], pIoctrl, sizeof(ioctrl_t));
i += sizeof(ioctrl_t);
return SCSI_CalCmd(buf, i, (BYTE*)pIoctrl, sizeof(ioctrl_t));
}
//---------------------------------------------------------------------------
//
// $56 - フラッシュ
//
//---------------------------------------------------------------------------
int FS_Flush()
{
BYTE buf[256];
DWORD *dp;
dp = (DWORD*)buf;
*dp = unit;
return SCSI_SendCmd(buf, 4);
}
//---------------------------------------------------------------------------
//
// $57 - メディア交換チェック
//
//---------------------------------------------------------------------------
int FS_CheckMedia()
{
BYTE buf[256];
DWORD *dp;
dp = (DWORD*)buf;
*dp = unit;
return SCSI_SendCmd(buf, 4);
}
//---------------------------------------------------------------------------
//
// $58 - 排他制御
//
//---------------------------------------------------------------------------
int FS_Lock()
{
BYTE buf[256];
DWORD *dp;
dp = (DWORD*)buf;
*dp = unit;
return SCSI_SendCmd(buf, 4);
}
//===========================================================================
//
// コマンドハンドラ
//
//===========================================================================
#define GetReqByte(a) (request[a])
#define SetReqByte(a,d) (request[a] = (d))
#define GetReqWord(a) (*((WORD*)&request[a]))
#define SetReqWord(a,d) (*((WORD*)&request[a]) = (d))
#define GetReqLong(a) (*((DWORD*)&request[a]))
#define SetReqLong(a,d) (*((DWORD*)&request[a]) = (d))
#define GetReqAddr(a) ((BYTE*)((*((DWORD*)&request[a])) & 0x00ffffff))
//---------------------------------------------------------------------------
//
// NAMESTS読み込み
//
//---------------------------------------------------------------------------
void GetNameStsPath(BYTE *addr, namests_t* pNamests)
{
DWORD i;
ASSERT(this);
ASSERT(pNamests);
// ワイルドカード情報
pNamests->wildcard = *addr;
// ドライブ番号
pNamests->drive = addr[1];
// パス名
for (i = 0; i < sizeof(pNamests->path); i++) {
pNamests->path[i] = addr[2 + i];
}
// ファイル名1
memset(pNamests->name, 0x20, sizeof(pNamests->name));
// 拡張子
memset(pNamests->ext, 0x20, sizeof(pNamests->ext));
// ファイル名2
memset(pNamests->add, 0, sizeof(pNamests->add));
}
//---------------------------------------------------------------------------
//
// NAMESTS読み込み
//
//---------------------------------------------------------------------------
void GetNameSts(BYTE *addr, namests_t* pNamests)
{
DWORD i;
ASSERT(this);
ASSERT(pNamests);
ASSERT(addr <= 0xFFFFFF);
// ワイルドカード情報
pNamests->wildcard = *addr;
// ドライブ番号
pNamests->drive = addr[1];
// パス名
for (i = 0; i < sizeof(pNamests->path); i++) {
pNamests->path[i] = addr[2 + i];
}
// ファイル名1
for (i = 0; i < sizeof(pNamests->name); i++) {
pNamests->name[i] = addr[67 + i];
}
// 拡張子
for (i = 0; i < sizeof(pNamests->ext); i++) {
pNamests->ext[i] = addr[75 + i];
}
// ファイル名2
for (i = 0; i < sizeof(pNamests->add); i++) {
pNamests->add[i] = addr[78 + i];
}
}
//---------------------------------------------------------------------------
//
// FILES読み込み
//
//---------------------------------------------------------------------------
void GetFiles(BYTE *addr, files_t* pFiles)
{
ASSERT(this);
ASSERT(pFiles);
ASSERT(addr <= 0xFFFFFF);
// 検索情報
pFiles->fatr = *addr;
pFiles->sector = *((DWORD*)&addr[2]);
pFiles->offset = *((WORD*)&addr[8]);;
pFiles->attr = 0;
pFiles->time = 0;
pFiles->date = 0;
pFiles->size = 0;
memset(pFiles->full, 0, sizeof(pFiles->full));
}
//---------------------------------------------------------------------------
//
// FILES書き込み
//
//---------------------------------------------------------------------------
void SetFiles(BYTE *addr, const files_t* pFiles)
{
DWORD i;
ASSERT(this);
ASSERT(pFiles);
*((DWORD*)&addr[2]) = pFiles->sector;
*((WORD*)&addr[8]) = pFiles->offset;
// ファイル情報
addr[21] = pFiles->attr;
*((WORD*)&addr[22]) = pFiles->time;
*((WORD*)&addr[24]) = pFiles->date;
*((DWORD*)&addr[26]) = pFiles->size;
// フルファイル名
addr += 30;
for (i = 0; i < sizeof(pFiles->full); i++) {
*addr = pFiles->full[i];
addr++;
}
}
//---------------------------------------------------------------------------
//
// FCB読み込み
//
//---------------------------------------------------------------------------
void GetFcb(BYTE *addr, fcb_t* pFcb)
{
ASSERT(this);
ASSERT(pFcb);
// FCB情報
pFcb->fileptr = *((DWORD*)&addr[6]);
pFcb->mode = *((WORD*)&addr[14]);
// 属性
pFcb->attr = addr[47];
// FCB情報
pFcb->time = *((WORD*)&addr[58]);
pFcb->date = *((WORD*)&addr[60]);
pFcb->size = *((DWORD*)&addr[64]);
}
//---------------------------------------------------------------------------
//
// FCB書き込み
//
//---------------------------------------------------------------------------
void SetFcb(BYTE *addr, const fcb_t* pFcb)
{
ASSERT(this);
ASSERT(pFcb);
// FCB情報
*((DWORD*)&addr[6]) = pFcb->fileptr;
*((WORD*)&addr[14]) = pFcb->mode;
// 属性
addr[47] = pFcb->attr;
// FCB情報
*((WORD*)&addr[58]) = pFcb->time;
*((WORD*)&addr[60]) = pFcb->date;
*((DWORD*)&addr[64]) = pFcb->size;
}
//---------------------------------------------------------------------------
//
// CAPACITY書き込み
//
//---------------------------------------------------------------------------
void SetCapacity(BYTE *addr, const capacity_t* pCapacity)
{
ASSERT(this);
ASSERT(pCapacity);
*((WORD*)&addr[0]) = pCapacity->freearea;
*((WORD*)&addr[2]) = pCapacity->clusters;
*((WORD*)&addr[4]) = pCapacity->sectors;
*((WORD*)&addr[6]) = pCapacity->bytes;
}
//---------------------------------------------------------------------------
//
// DPB書き込み
//
//---------------------------------------------------------------------------
void SetDpb(BYTE *addr, const dpb_t* pDpb)
{
ASSERT(this);
ASSERT(pDpb);
// DPB情報
*((WORD*)&addr[0]) = pDpb->sector_size;
addr[2] = pDpb->cluster_size;
addr[3] = pDpb->shift;
*((WORD*)&addr[4]) = pDpb->fat_sector;
addr[6] = pDpb->fat_max;
addr[7] = pDpb->fat_size;
*((WORD*)&addr[8]) = pDpb->file_max;
*((WORD*)&addr[10]) = pDpb->data_sector;
*((WORD*)&addr[12]) = pDpb->cluster_max;
*((WORD*)&addr[14]) = pDpb->root_sector;
addr[20] = pDpb->media;
}
//---------------------------------------------------------------------------
//
// IOCTRL読み込み
//
//---------------------------------------------------------------------------
void GetIoctrl(DWORD param, DWORD func, ioctrl_t* pIoctrl)
{
DWORD *lp;
ASSERT(this);
ASSERT(pIoctrl);
switch (func) {
case 2:
// メディア再認識
pIoctrl->param = param;
return;
case -2:
// オプション設定
lp = (DWORD*)param;
pIoctrl->param = *lp;
return;
}
}
//---------------------------------------------------------------------------
//
// IOCTRL書き込み
//
//---------------------------------------------------------------------------
void SetIoctrl(DWORD param, DWORD func, ioctrl_t* pIoctrl)
{
DWORD i;
BYTE *bp;
WORD *wp;
DWORD *lp;
ASSERT(this);
ASSERT(pIoctrl);
switch (func) {
case 0:
// メディアIDの獲得
wp = (WORD*)param;
*wp = pIoctrl->media;
return;
case 1:
// Human68k互換のためのダミー
lp = (DWORD*)param;
*lp = pIoctrl->param;
return;
case -1:
// 常駐判定
bp = (BYTE*)param;
for (i = 0; i < 8; i++) {
*bp = pIoctrl->buffer[i];
bp++;
}
return;
case -3:
// オプション獲得
lp = (DWORD*)param;
*lp = pIoctrl->param;
return;
}
}
//---------------------------------------------------------------------------
//
// ARGUMENT読み込み
//
// バッファサイズよりも長い場合は転送を打ち切って必ず終端する。
//
//---------------------------------------------------------------------------
void GetArgument(BYTE *addr, argument_t* pArgument)
{
BOOL bMode;
BYTE *p;
DWORD i;
BYTE c;
ASSERT(this);
ASSERT(pArgument);
bMode = FALSE;
p = pArgument->buf;
for (i = 0; i < sizeof(pArgument->buf) - 2; i++) {
c = addr[i];
*p++ = c;
if (bMode == 0) {
if (c == '\0')
return;
bMode = TRUE;
} else {
if (c == '\0')
bMode = FALSE;
}
}
*p++ = '\0';
*p = '\0';
}
//---------------------------------------------------------------------------
//
// 終了値書き込み
//
//---------------------------------------------------------------------------
void SetResult(DWORD nResult)
{
DWORD code;
ASSERT(this);
// 致命的エラー判定
switch (nResult) {
case FS_FATAL_INVALIDUNIT:
code = 0x5001;
goto fatal;
case FS_FATAL_INVALIDCOMMAND:
code = 0x5003;
goto fatal;
case FS_FATAL_WRITEPROTECT:
code = 0x700D;
goto fatal;
case FS_FATAL_MEDIAOFFLINE:
code = 0x7002;
fatal:
SetReqByte(3, (BYTE)code);
SetReqByte(4, code >> 8);
// @note リトライ可能を返すときは、(a5 + 18)を書き換えてはいけない。
// その後白帯で Retry を選択した場合、書き換えた値を読み込んで誤動作してしまう。
if (code & 0x2000)
break;
nResult = FS_INVALIDFUNC;
default:
SetReqLong(18, nResult);
break;
}
}
//---------------------------------------------------------------------------
//
// $40 - デバイス起動
//
// in (offset size)
// 0 1.b 定数(22)
// 2 1.b コマンド($40/$c0)
// 18 1.l パラメータアドレス
// 22 1.b ドライブ番号
// out (offset size)
// 3 1.b エラーコード(下位)
// 4 1.b 〃 (上位)
// 13 1.b ユニット数
// 14 1.l デバイスドライバの終了アドレス + 1
//
// ローカルドライブのコマンド 0 と同様に組み込み時に呼ばれるが、BPB 及
// びそのポインタの配列を用意する必要はない.
// 他のコマンドと違い、このコマンドだけa5 + 1には有効な値が入っていない
// (0初期化なども期待してはいけない)ので注意すること。
//
//---------------------------------------------------------------------------
DWORD InitDevice(void)
{
argument_t arg;
DWORD units;
ASSERT(this);
ASSERT(fs);
// オプション内容を獲得
GetArgument(GetReqAddr(18), &arg);
// Human68k側で利用可能なドライブ数の範囲で、ファイルシステムを構築
units = FS_InitDevice(&arg);
// ドライブ数を返信
SetReqByte(13, units);
return 0;
}
//---------------------------------------------------------------------------
//
// $41 - ディレクトリチェック
//
// in (offset size)
// 14 1.L NAMESTS構造体アドレス
//
//---------------------------------------------------------------------------
DWORD CheckDir(void)
{
namests_t ns;
int nResult;
ASSERT(this);
ASSERT(fs);
// 検索対象ファイル名獲得
GetNameStsPath(GetReqAddr(14), &ns);
// ファイルシステム呼び出し
nResult = FS_CheckDir(&ns);
return nResult;
}
//---------------------------------------------------------------------------
//
// $42 - ディレクトリ作成
//
// in (offset size)
// 14 1.L NAMESTS構造体アドレス
//
//---------------------------------------------------------------------------
DWORD MakeDir(void)
{
namests_t ns;
int nResult;
ASSERT(this);
ASSERT(fs);
// 検索対象ファイル名獲得
GetNameSts(GetReqAddr(14), &ns);
// ファイルシステム呼び出し
nResult = FS_MakeDir(&ns);
return nResult;
}
//---------------------------------------------------------------------------
//
// $43 - ディレクトリ削除
//
// in (offset size)
// 14 1.L NAMESTS構造体アドレス
//
//---------------------------------------------------------------------------
DWORD RemoveDir(void)
{
namests_t ns;
int nResult;
ASSERT(this);
ASSERT(fs);
// 検索対象ファイル名獲得
GetNameSts(GetReqAddr(14), &ns);
// ファイルシステム呼び出し
nResult = FS_RemoveDir(&ns);
return nResult;
}
//---------------------------------------------------------------------------
//
// $44 - ファイル名変更
//
// in (offset size)
// 14 1.L NAMESTS構造体アドレス 旧ファイル名
// 18 1.L NAMESTS構造体アドレス 新ファイル名
//
//---------------------------------------------------------------------------
DWORD Rename(void)
{
namests_t ns;
namests_t ns_new;
int nResult;
ASSERT(this);
ASSERT(fs);
// 検索対象ファイル名獲得
GetNameSts(GetReqAddr(14), &ns);
GetNameSts(GetReqAddr(18), &ns_new);
// ファイルシステム呼び出し
nResult = FS_Rename(&ns, &ns_new);
return nResult;
}
//---------------------------------------------------------------------------
//
// $45 - ファイル削除
//
// in (offset size)
// 14 1.L NAMESTS構造体アドレス
//
//---------------------------------------------------------------------------
DWORD Delete(void)
{
namests_t ns;
int nResult;
ASSERT(this);
ASSERT(fs);
// 検索対象ファイル名獲得
GetNameSts(GetReqAddr(14), &ns);
// ファイルシステム呼び出し
nResult = FS_Delete(&ns);
return nResult;
}
//---------------------------------------------------------------------------
//
// $46 - ファイル属性取得/設定
//
// in (offset size)
// 12 1.B 読み出し時に0x01になるので注意
// 13 1.B 属性 $FFだと読み出し
// 14 1.L NAMESTS構造体アドレス
//
//---------------------------------------------------------------------------
DWORD Attribute(void)
{
namests_t ns;
DWORD attr;
int nResult;
ASSERT(this);
ASSERT(fs);
// 検索対象ファイル名獲得
GetNameSts(GetReqAddr(14), &ns);
// 対象属性
attr = GetReqByte(13);
// ファイルシステム呼び出し
nResult = FS_Attribute(&ns, attr);
return nResult;
}
//---------------------------------------------------------------------------
//
// $47 - ファイル検索
//
// in (offset size)
// 0 1.b 定数(26)
// 1 1.b ユニット番号
// 2 1.b コマンド($47/$c7)
// 13 1.b 検索属性 (WindrvXMでは未使用。検索バッファに値が書かれている)
// 14 1.l ファイル名バッファ(namests 形式)
// 18 1.l 検索バッファ(files 形式) このバッファに検索途中情報と検索結果を書き込む
// out (offset size)
// 3 1.b エラーコード(下位)
// 4 1.b 〃 (上位)
// 18 1.l リザルトステータス
//
// ディレクトリから指定ファイルを検索する. DOS _FILES から呼び出される.
// 検索に失敗した場合、若しくは検索に成功してもワイルドカードが使われて
// いない場合は、次回検索時に必ず失敗させる為に検索バッファのオフセットに
// -1 を書き込む. 検索が成功した場合は見つかったファイルの情報を設定する
// と共に、次検索用の情報のセクタ番号、オフセット、ルートディレクトリの場
// 合は更に残りセクタ数を設定する. 検索ドライブ・属性、パス名は DOS コー
// ル処理内で設定されるので書き込む必要はない.
//
// <NAMESTS構造体>
// (offset size)
// 0 1.b NAMWLD 0:ワイルドカードなし -1:ファイル指定なし
// (ワイルドカードの文字数)
// 1 1.b NAMDRV ドライブ番号(A=0,B=1,…,Z=25)
// 2 65.b NAMPTH パス('\'+あればサブディレクトリ名+'\')
// 67 8.b NAMNM1 ファイル名(先頭 8 文字)
// 75 3.b NAMEXT 拡張子
// 78 10.b NAMNM2 ファイル名(残りの 10 文字)
//
// パス区切り文字は0x2F(/)や0x5C(\)ではなく0x09(TAB)を使っているので注意。
//
//---------------------------------------------------------------------------
DWORD Files(void)
{
BYTE *files;
files_t info;
namests_t ns;
int nResult;
ASSERT(this);
ASSERT(fs);
// 検索途中経過格納領域
files = GetReqAddr(18);
GetFiles(files, &info);
// 検索対象ファイル名獲得
GetNameSts(GetReqAddr(14), &ns);
// ファイルシステム呼び出し
nResult = FS_Files((DWORD)files, &ns, &info);
// 検索結果の反映
if (nResult >= 0) {
SetFiles(files, &info);
}
return nResult;
}
//---------------------------------------------------------------------------
//
// $48 - ファイル次検索
//
// in (offset size)
// 18 1.L FILES構造体アドレス
//
//---------------------------------------------------------------------------
DWORD NFiles(void)
{
BYTE *files;
files_t info;
int nResult;
ASSERT(this);
ASSERT(fs);
// ワーク領域の読み込み
files = GetReqAddr(18);
GetFiles(files, &info);
// ファイルシステム呼び出し
nResult = FS_NFiles((DWORD)files, &info);
// 検索結果の反映
if (nResult >= 0) {
SetFiles(files, &info);
}
return nResult;
}
//---------------------------------------------------------------------------
//
// $49 - ファイル作成(Create)
//
// in (offset size)
// 1 1.B ユニット番号
// 13 1.B 属性
// 14 1.L NAMESTS構造体アドレス
// 18 1.L モード (0:_NEWFILE 1:_CREATE)
// 22 1.L FCB構造体アドレス
//
//---------------------------------------------------------------------------
DWORD Create(void)
{
namests_t ns;
BYTE *pFcb;
fcb_t fcb;
DWORD attr;
BOOL force;
int nResult;
ASSERT(this);
ASSERT(fs);
// 対象ファイル名獲得
GetNameSts(GetReqAddr(14), &ns);
// FCB獲得
pFcb = GetReqAddr(22);
GetFcb(pFcb, &fcb);
// 属性
attr = GetReqByte(13);
// 強制上書きモード
force = (BOOL)GetReqLong(18);
// ファイルシステム呼び出し
nResult = FS_Create((DWORD)pFcb, &ns, &fcb, attr, force);
// 結果の反映
if (nResult >= 0) {
SetFcb(pFcb, &fcb);
}
return nResult;
}
//---------------------------------------------------------------------------
//
// $4A - ファイルオープン
//
// in (offset size)
// 1 1.B ユニット番号
// 14 1.L NAMESTS構造体アドレス
// 22 1.L FCB構造体アドレス
// 既にFCBにはほとんどのパラメータが設定済み
// 時刻・日付はオープンした瞬間のものになってるので上書き
// サイズは0になっているので上書き
//
//---------------------------------------------------------------------------
DWORD Open(void)
{
namests_t ns;
BYTE *pFcb;
fcb_t fcb;
int nResult;
ASSERT(this);
ASSERT(fs);
// 対象ファイル名獲得
GetNameSts(GetReqAddr(14), &ns);
// FCB獲得
pFcb = GetReqAddr(22);
GetFcb(pFcb, &fcb);
// ファイルシステム呼び出し
nResult = FS_Open((DWORD)pFcb, &ns, &fcb);
// 結果の反映
if (nResult >= 0) {
SetFcb(pFcb, &fcb);
}
return nResult;
}
//---------------------------------------------------------------------------
//
// $4B - ファイルクローズ
//
// in (offset size)
// 22 1.L FCB構造体アドレス
//
//---------------------------------------------------------------------------
DWORD Close(void)
{
BYTE *pFcb;
fcb_t fcb;
int nResult;
ASSERT(this);
ASSERT(fs);
// FCB獲得
pFcb = GetReqAddr(22);
GetFcb(pFcb, &fcb);
// ファイルシステム呼び出し
nResult = FS_Close((DWORD)pFcb, &fcb);
// 結果の反映
if (nResult >= 0) {
SetFcb(pFcb, &fcb);
}
return nResult;
}
//---------------------------------------------------------------------------
//
// $4C - ファイル読み込み
//
// in (offset size)
// 14 1.L 読み込みバッファ ここにファイル内容を読み込む
// 18 1.L サイズ 16MBを超える値が指定される可能性もあり
// 22 1.L FCB構造体アドレス
//
// バスエラーが発生するアドレスを指定した場合の動作は保証しない。
//
// 20世紀のアプリは「負の数だとファイルを全部読む」という作法で書かれている
// 可能性が微レ存。あれれーこのファイル16MB超えてるよー(CV.高山みなみ)
//
// むしろ412MBくらいの当時のプログラマーから見た実質的な「∞」の値で
// クリップするような配慮こそが現代では必要なのではなかろうか。
// または、末尾が12MBと16MB位置を超えたらサイズをクリップすると良いかも。
//
//---------------------------------------------------------------------------
DWORD Read(void)
{
BYTE *pFcb;
fcb_t fcb;
BYTE *pAddress;
DWORD nSize;
int nResult;
ASSERT(this);
ASSERT(fs);
// FCB獲得
pFcb = GetReqAddr(22);
GetFcb(pFcb, &fcb);
// 読み込みバッファ
pAddress = GetReqAddr(14);
// 読み込みサイズ
nSize = GetReqLong(18);
// クリッピング
if (nSize >= WINDRV_CLIPSIZE_MAX) {
nSize = WINDRV_CLIPSIZE_MAX;
}
// ファイルシステム呼び出し
nResult = FS_Read((DWORD)pFcb, &fcb, pAddress, nSize);
// 結果の反映
if (nResult >= 0) {
SetFcb(pFcb, &fcb);
}
return nResult;
}
//---------------------------------------------------------------------------
//
// $4D - ファイル書き込み
//
// in (offset size)
// 14 1.L 書き込みバッファ ここにファイル内容を書き込む
// 18 1.L サイズ 負の数ならファイルサイズを指定したのと同じ
// 22 1.L FCB構造体アドレス
//
// バスエラーが発生するアドレスを指定した場合の動作は保証しない。
//
//---------------------------------------------------------------------------
DWORD Write(void)
{
BYTE *pFcb;
fcb_t fcb;
BYTE *pAddress;
DWORD nSize;
int nResult;
ASSERT(this);
ASSERT(fs);
// FCB獲得
pFcb = GetReqAddr(22);
GetFcb(pFcb, &fcb);
// 書き込みバッファ
pAddress = GetReqAddr(14);
// 書き込みサイズ
nSize = GetReqLong(18);
// クリッピング
if (nSize >= WINDRV_CLIPSIZE_MAX) {
nSize = WINDRV_CLIPSIZE_MAX;
}
// ファイルシステム呼び出し
nResult = FS_Write((DWORD)pFcb, &fcb, pAddress, nSize);
// 結果の反映
if (nResult >= 0) {
SetFcb(pFcb, &fcb);
}
return nResult;
}
//---------------------------------------------------------------------------
//
// $4E - ファイルシーク
//
// in (offset size)
// 12 1.B 0x2B になってるときがある 0のときもある
// 13 1.B モード
// 18 1.L オフセット
// 22 1.L FCB構造体アドレス
//
//---------------------------------------------------------------------------
DWORD Seek(void)
{
BYTE *pFcb;
fcb_t fcb;
DWORD nMode;
DWORD nOffset;
int nResult;
ASSERT(this);
ASSERT(fs);
// FCB獲得
pFcb = GetReqAddr(22);
GetFcb(pFcb, &fcb);
// シークモード
nMode = GetReqByte(13);
// シークオフセット
nOffset = GetReqLong(18);
// ファイルシステム呼び出し
nResult = FS_Seek((DWORD)pFcb, &fcb, nMode, nOffset);
// 結果の反映
if (nResult >= 0) {
SetFcb(pFcb, &fcb);
}
return nResult;
}
//---------------------------------------------------------------------------
//
// $4F - ファイル時刻取得/設定
//
// in (offset size)
// 18 1.W DATE
// 20 1.W TIME
// 22 1.L FCB構造体アドレス
//
// FCBが読み込みモードで開かれた状態でも設定変更が可能。
// FCBだけでは書き込み禁止の判定ができないので注意。
//
//---------------------------------------------------------------------------
DWORD TimeStamp(void)
{
BYTE *pFcb;
fcb_t fcb;
DWORD nTime;
DWORD nResult;
ASSERT(this);
ASSERT(fs);
// FCB獲得
pFcb = GetReqAddr(22);
GetFcb(pFcb, &fcb);
// 時刻獲得
nTime = GetReqLong(18);
// ファイルシステム呼び出し
nResult = FS_TimeStamp((DWORD)pFcb, &fcb, nTime);
// 結果の反映
if (nResult < 0xFFFF0000) {
SetFcb(pFcb, &fcb);
}
return nResult;
}
//---------------------------------------------------------------------------
//
// $50 - 容量取得
//
// in (offset size)
// 0 1.b 定数(26)
// 1 1.b ユニット番号
// 2 1.b コマンド($50/$d0)
// 14 1.l バッファアドレス
// out (offset size)
// 3 1.b エラーコード(下位)
// 4 1.b 〃 (上位)
// 18 1.l リザルトステータス
//
// メディアの総容量/空き容量、クラスタ/セクタサイズを収得する. バッファ
// に書き込む内容は以下の通り. リザルトステータスとして使用可能なバイト数
// を返すこと.
//
// (offset size)
// 0 1.w 使用可能なクラスタ数
// 2 1.w 総クラスタ数
// 4 1.w 1 クラスタ当りのセクタ数
// 6 1.w 1 セクタ当りのバイト数
//
//---------------------------------------------------------------------------
DWORD GetCapacity(void)
{
BYTE *pCapacity;
capacity_t cap;
int nResult;
ASSERT(this);
ASSERT(fs);
// バッファ取得
pCapacity = GetReqAddr(14);
#if 0
// ファイルシステム呼び出し
nResult = FS_GetCapacity(&cap);
#else
// いつも同じ内容が返ってくるのでスキップしてみる
cap.freearea = 0xFFFF;
cap.clusters = 0xFFFF;
cap.sectors = 64;
cap.bytes = 512;
nResult = 0x7FFF8000;
#endif
// 結果の反映
if (nResult >= 0) {
SetCapacity(pCapacity, &cap);
}
return nResult;
}
//---------------------------------------------------------------------------
//
// $51 - ドライブ状態検査/制御
//
// in (offset size)
// 1 1.B ユニット番号
// 13 1.B 状態 0: 状態検査 1: イジェクト
//
//---------------------------------------------------------------------------
DWORD CtrlDrive(void)
{
ctrldrive_t ctrl;
int nResult;
ASSERT(this);
ASSERT(fs);
// ドライブ状態取得
ctrl.status = GetReqByte(13);
// ファイルシステム呼び出し
nResult = FS_CtrlDrive(&ctrl);
// 結果の反映
if (nResult >= 0) {
SetReqByte(13, ctrl.status);
}
return nResult;
}
//---------------------------------------------------------------------------
//
// $52 - DPB取得
//
// in (offset size)
// 0 1.b 定数(26)
// 1 1.b ユニット番号
// 2 1.b コマンド($52/$d2)
// 14 1.l バッファアドレス(先頭アドレス + 2 を指す)
// out (offset size)
// 3 1.b エラーコード(下位)
// 4 1.b 〃 (上位)
// 18 1.l リザルトステータス
//
// 指定メディアの情報を v1 形式 DPB で返す. このコマンドで設定する必要
// がある情報は以下の通り(括弧内は DOS コールが設定する). ただし、バッフ
// ァアドレスはオフセット 2 を指したアドレスが渡されるので注意すること.
//
// (offset size)
// 0 1.b (ドライブ番号)
// 1 1.b (ユニット番号)
// 2 1.w 1 セクタ当りのバイト数
// 4 1.b 1 クラスタ当りのセクタ数 - 1
// 5 1.b クラスタ→セクタのシフト数
// bit 7 = 1 で MS-DOS 形式 FAT(16bit Intel 配列)
// 6 1.w FAT の先頭セクタ番号
// 8 1.b FAT 領域の個数
// 9 1.b FAT の占めるセクタ数(複写分を除く)
// 10 1.w ルートディレクトリに入るファイルの個数
// 12 1.w データ領域の先頭セクタ番号
// 14 1.w 総クラスタ数 + 1
// 16 1.w ルートディレクトリの先頭セクタ番号
// 18 1.l (ドライバヘッダのアドレス)
// 22 1.b (小文字の物理ドライブ名)
// 23 1.b (DPB 使用フラグ:常に 0)
// 24 1.l (次の DPB のアドレス)
// 28 1.w (カレントディレクトリのクラスタ番号:常に 0)
// 30 64.b (カレントディレクトリ名)
//
//---------------------------------------------------------------------------
DWORD GetDPB(void)
{
BYTE *pDpb;
dpb_t dpb;
int nResult;
ASSERT(this);
ASSERT(fs);
// DPB取得
pDpb = GetReqAddr(14);
// ファイルシステム呼び出し
nResult = FS_GetDPB(&dpb);
// 結果の反映
if (nResult >= 0) {
SetDpb(pDpb, &dpb);
}
return nResult;
}
//---------------------------------------------------------------------------
//
// $53 - セクタ読み込み
//
// in (offset size)
// 1 1.B ユニット番号
// 14 1.L バッファアドレス
// 18 1.L セクタ数
// 22 1.L セクタ番号
//
//---------------------------------------------------------------------------
DWORD DiskRead(void)
{
BYTE *pAddress;
DWORD nSize;
DWORD nSector;
BYTE buffer[0x200];
int nResult;
int i;
ASSERT(this);
ASSERT(fs);
pAddress = GetReqAddr(14); // アドレス (上位ビットが拡張フラグ)
nSize = GetReqLong(18); // セクタ数
nSector = GetReqLong(22); // セクタ番号
// ファイルシステム呼び出し
nResult = FS_DiskRead(buffer, nSector, nSize);
// 結果の反映
if (nResult >= 0) {
for (i = 0; i < sizeof(buffer); i++) {
*pAddress = buffer[i];
pAddress++;
}
}
return nResult;
}
//---------------------------------------------------------------------------
//
// $54 - セクタ書き込み
//
// in (offset size)
// 1 1.B ユニット番号
// 14 1.L バッファアドレス
// 18 1.L セクタ数
// 22 1.L セクタ番号
//
//---------------------------------------------------------------------------
DWORD DiskWrite(void)
{
BYTE *pAddress;
DWORD nSize;
DWORD nSector;
int nResult;
ASSERT(this);
ASSERT(fs);
pAddress = GetReqAddr(14); // アドレス(上位ビットが拡張フラグ)
nSize = GetReqLong(18); // セクタ数
nSector = GetReqLong(22); // セクタ番号
// ファイルシステム呼び出し
nResult = FS_DiskWrite();
return nResult;
}
//---------------------------------------------------------------------------
//
// $55 - IOCTRL
//
// in (offset size)
// 1 1.B ユニット番号
// 14 1.L パラメータ
// 18 1.W 機能番号
//
//---------------------------------------------------------------------------
DWORD Ioctrl(void)
{
DWORD param;
DWORD func;
ioctrl_t ioctrl;
int nResult;
ASSERT(this);
ASSERT(fs);
// IOCTRL取得
param = GetReqLong(14); // パラメータ
func = GetReqWord(18); // 機能番号
GetIoctrl(param, func, &ioctrl);
// ファイルシステム呼び出し
nResult = FS_Ioctrl(func, &ioctrl);
// 結果の反映
if (nResult >= 0)
SetIoctrl(param, func, &ioctrl);
return nResult;
}
//---------------------------------------------------------------------------
//
// $56 - フラッシュ
//
// in (offset size)
// 1 1.B ユニット番号
//
//---------------------------------------------------------------------------
DWORD Flush(void)
{
int nResult;
ASSERT(this);
ASSERT(fs);
// ファイルシステム呼び出し
nResult = FS_Flush();
return nResult;
}
//---------------------------------------------------------------------------
//
// $57 - メディア交換チェック
//
// in (offset size)
// 0 1.b 定数(26)
// 1 1.b ユニット番号
// 2 1.b コマンド($57/$d7)
// out (offset size)
// 3 1.b エラーコード(下位)
// 4 1.b 〃 (上位)
// 18 1.l リザルトステータス
//
// メディアが交換されたか否かを調べる. 交換されていた場合のフォーマット
// 確認はこのコマンド内で行うこと.
//
//---------------------------------------------------------------------------
DWORD CheckMedia(void)
{
#if 1
static DWORD last = 0;
DWORD now;
#endif
int nResult;
ASSERT(this);
ASSERT(fs);
#if 1
// 連続で呼び出されるの回避する
now = TIMEGET();
if ((now - last) < 3) {
return 0;
} else {
last = now;
}
#endif
// ファイルシステム呼び出し
nResult = FS_CheckMedia();
return nResult;
}
//---------------------------------------------------------------------------
//
// $58 - 排他制御
//
// in (offset size)
// 1 1.B ユニット番号
//
//---------------------------------------------------------------------------
DWORD Lock(void)
{
int nResult;
ASSERT(this);
ASSERT(fs);
// ファイルシステム呼び出し
nResult = FS_Lock();
return nResult;
}
//---------------------------------------------------------------------------
//
// コマンド実行
//
//---------------------------------------------------------------------------
DWORD ExecuteCommand()
{
ASSERT(this);
// エラー情報クリア
SetReqByte(3, 0);
SetReqByte(4, 0);
// コマンド番号
command = (DWORD)GetReqByte(2); // ビット7はベリファイフラグ
// ユニット番号
unit = GetReqByte(1);
// コマンド分岐
switch (command & 0x7F) {
case 0x40: return InitDevice(); // $40 - デバイス起動
case 0x41: return CheckDir(); // $41 - ディレクトリチェック
case 0x42: return MakeDir(); // $42 - ディレクトリ作成
case 0x43: return RemoveDir(); // $43 - ディレクトリ削除
case 0x44: return Rename(); // $44 - ファイル名変更
case 0x45: return Delete(); // $45 - ファイル削除
case 0x46: return Attribute(); // $46 - ファイル属性取得/設定
case 0x47: return Files(); // $47 - ファイル検索
case 0x48: return NFiles(); // $48 - ファイル次検索
case 0x49: return Create(); // $49 - ファイル作成
case 0x4A: return Open(); // $4A - ファイルオープン
case 0x4B: return Close(); // $4B - ファイルクローズ
case 0x4C: return Read(); // $4C - ファイル読み込み
case 0x4D: return Write(); // $4D - ファイル書き込み
case 0x4E: return Seek(); // $4E - ファイルシーク
case 0x4F: return TimeStamp(); // $4F - ファイル更新時刻の取得/設定
case 0x50: return GetCapacity();// $50 - 容量取得
case 0x51: return CtrlDrive(); // $51 - ドライブ制御/状態検査
case 0x52: return GetDPB(); // $52 - DPB取得
case 0x53: return DiskRead(); // $53 - セクタ読み込み
case 0x54: return DiskWrite(); // $54 - セクタ書き込み
case 0x55: return Ioctrl(); // $55 - IOCTRL
#if 0
case 0x56: return Flush(); // $56 - フラッシュ
#else
case 0x56: return 0; // $56 - フラッシュ
#endif
case 0x57: return CheckMedia(); // $57 - メディア交換チェック
#if 0
case 0x58: return Lock(); // $58 - 排他制御
#else
case 0x58: return 0; // $58 - 排他制御
#endif
}
return FS_FATAL_INVALIDCOMMAND;
}
//---------------------------------------------------------------------------
//
// 初期化
//
//---------------------------------------------------------------------------
BOOL Init()
{
ASSERT(this);
return SCSI_Init();
}
//---------------------------------------------------------------------------
//
// 実行
//
//---------------------------------------------------------------------------
void Process(DWORD nA5)
{
ASSERT(this);
ASSERT(nA5 <= 0xFFFFFF);
ASSERT(m_bAlloc);
ASSERT(m_bFree);
// リクエストヘッダのアドレス
request = (BYTE*)nA5;
// コマンド実行
SetResult(ExecuteCommand());
}