//--------------------------------------------------------------------------- // // SCSI Target Emulator RaSCSI (*^..^*) // for Raspberry Pi // // Powered by XM6 TypeG Technorogy. // Copyright (C) 2016-2017 GIMONS // [ ホストファイルシステム ブリッジドライバ ] // //--------------------------------------------------------------------------- #include #include #include #include #include #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 コー // ル処理内で設定されるので書き込む必要はない. // // // (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.高山みなみ) // // むしろ4〜12MBくらいの当時のプログラマーから見た実質的な「∞」の値で // クリップするような配慮こそが現代では必要なのではなかろうか。 // または、末尾が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()); }