RASCSI/src_old/raspberrypi/devices/scsi_host_bridge.cpp

1185 lines
28 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
//
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
// Copyright (C) 2014-2020 GIMONS
// Copyright (C) akuker
//
// Licensed under the BSD 3-Clause License.
// See LICENSE file in the project root folder.
//
// [ SCSI Host Bridge for the Sharp X68000 ]
//
// Note: This requires a special driver on the host system and will only
// work with the Sharp X68000 operating system.
//---------------------------------------------------------------------------
#include "controllers/scsidev_ctrl.h"
#include "scsi_host_bridge.h"
#include "ctapdriver.h"
#include "cfilesystem.h"
using namespace std;
using namespace scsi_defs;
SCSIBR::SCSIBR() : Disk("SCBR")
{
tap = NULL;
m_bTapEnable = false;
packet_enable = false;
fsoptlen = 0;
fsoutlen = 0;
fsresult = 0;
packet_len = 0;
// Create host file system
fs = new CFileSys();
fs->Reset();
dispatcher.AddCommand(eCmdTestUnitReady, "TestUnitReady", &SCSIBR::TestUnitReady);
dispatcher.AddCommand(eCmdRead6, "GetMessage10", &SCSIBR::GetMessage10);
dispatcher.AddCommand(eCmdWrite6, "SendMessage10", &SCSIBR::SendMessage10);
}
SCSIBR::~SCSIBR()
{
// TAP driver release
if (tap) {
tap->Cleanup();
delete tap;
}
// Release host file system
if (fs) {
fs->Reset();
delete fs;
}
}
bool SCSIBR::Init(const map<string, string>& params)
{
SetParams(params);
#ifdef __linux__
// TAP Driver Generation
tap = new CTapDriver();
m_bTapEnable = tap->Init(GetParams());
if (!m_bTapEnable){
LOGERROR("Unable to open the TAP interface");
return false;
}
// Generate MAC Address
memset(mac_addr, 0x00, 6);
if (m_bTapEnable) {
tap->GetMacAddr(mac_addr);
mac_addr[5]++;
}
// Packet reception flag OFF
packet_enable = false;
#endif
SetReady(m_bTapEnable);
// Not terminating on regular Linux PCs is helpful for testing
#if defined(__x86_64__) || defined(__X86__)
return true;
#else
return m_bTapEnable;
#endif
}
bool SCSIBR::Dispatch(SCSIDEV *controller)
{
// The superclass class handles the less specific commands
return dispatcher.Dispatch(this, controller) ? true : super::Dispatch(controller);
}
//---------------------------------------------------------------------------
//
// INQUIRY
//
//---------------------------------------------------------------------------
int SCSIBR::Inquiry(const DWORD *cdb, BYTE *buf)
{
// EVPD check
if (cdb[1] & 0x01) {
SetStatusCode(STATUS_INVALIDCDB);
return 0;
}
// Basic data
// buf[0] ... Communication Device
// buf[2] ... SCSI-2 compliant command system
// buf[3] ... SCSI-2 compliant Inquiry response
// buf[4] ... Inquiry additional data
memset(buf, 0, 8);
buf[0] = 0x09;
buf[2] = 0x02;
buf[3] = 0x02;
buf[4] = 0x1F + 8; // required + 8 byte extension
// Padded vendor, product, revision
memcpy(&buf[8], GetPaddedName().c_str(), 28);
// Optional function valid flag
buf[36] = '0';
// TAP Enable
if (m_bTapEnable) {
buf[37] = '1';
}
// CFileSys Enable
buf[38] = '1';
// Size of data that can be returned
int size = (buf[4] + 5);
// Limit if the other buffer is small
if (size > (int)cdb[4]) {
size = (int)cdb[4];
}
// Success
return size;
}
void SCSIBR::TestUnitReady(SASIDEV *controller)
{
// Always successful
controller->Status();
}
int SCSIBR::GetMessage10(const DWORD *cdb, BYTE *buf)
{
// Type
int type = cdb[2];
// Function number
int func = cdb[3];
// Phase
int phase = cdb[9];
switch (type) {
case 1: // Ethernet
// Do not process if TAP is invalid
if (!m_bTapEnable) {
return 0;
}
switch (func) {
case 0: // Get MAC address
return GetMacAddr(buf);
case 1: // Received packet acquisition (size/buffer)
if (phase == 0) {
// Get packet size
ReceivePacket();
buf[0] = (BYTE)(packet_len >> 8);
buf[1] = (BYTE)packet_len;
return 2;
} else {
// Get package data
GetPacketBuf(buf);
return packet_len;
}
case 2: // Received packet acquisition (size + buffer simultaneously)
ReceivePacket();
buf[0] = (BYTE)(packet_len >> 8);
buf[1] = (BYTE)packet_len;
GetPacketBuf(&buf[2]);
return packet_len + 2;
case 3: // Simultaneous acquisition of multiple packets (size + buffer simultaneously)
// Currently the maximum number of packets is 10
// Isn't it too fast if I increase more?
int total_len = 0;
for (int i = 0; i < 10; i++) {
ReceivePacket();
*buf++ = (BYTE)(packet_len >> 8);
*buf++ = (BYTE)packet_len;
total_len += 2;
if (packet_len == 0)
break;
GetPacketBuf(buf);
buf += packet_len;
total_len += packet_len;
}
return total_len;
}
break;
case 2: // Host Drive
switch (phase) {
case 0: // Get result code
return ReadFsResult(buf);
case 1: // Return data acquisition
return ReadFsOut(buf);
case 2: // Return additional data acquisition
return ReadFsOpt(buf);
}
break;
}
// Error
ASSERT(false);
return 0;
}
bool SCSIBR::SendMessage10(const DWORD *cdb, BYTE *buf)
{
// Type
int type = cdb[2];
// Function number
int func = cdb[3];
// Phase
int phase = cdb[9];
// Get the number of lights
int len = cdb[6];
len <<= 8;
len |= cdb[7];
len <<= 8;
len |= cdb[8];
switch (type) {
case 1: // Ethernet
// Do not process if TAP is invalid
if (!m_bTapEnable) {
return false;
}
switch (func) {
case 0: // MAC address setting
SetMacAddr(buf);
return true;
case 1: // Send packet
SendPacket(buf, len);
return true;
}
break;
case 2: // Host drive
switch (phase) {
case 0: // issue command
WriteFs(func, buf);
return true;
case 1: // additional data writing
WriteFsOpt(buf, len);
return true;
}
break;
}
// Error
ASSERT(false);
return false;
}
void SCSIBR::GetMessage10(SASIDEV *controller)
{
// Reallocate buffer (because it is not transfer for each block)
if (ctrl->bufsize < 0x1000000) {
free(ctrl->buffer);
ctrl->bufsize = 0x1000000;
ctrl->buffer = (BYTE *)malloc(ctrl->bufsize);
}
ctrl->length = GetMessage10(ctrl->cmd, ctrl->buffer);
if (ctrl->length <= 0) {
// Failure (Error)
controller->Error();
return;
}
// Set next block
ctrl->blocks = 1;
ctrl->next = 1;
controller->DataIn();
}
//---------------------------------------------------------------------------
//
// SEND MESSAGE(10)
//
// This Send Message command is used by the X68000 host driver
//
//---------------------------------------------------------------------------
void SCSIBR::SendMessage10(SASIDEV *controller)
{
// Reallocate buffer (because it is not transfer for each block)
if (ctrl->bufsize < 0x1000000) {
free(ctrl->buffer);
ctrl->bufsize = 0x1000000;
ctrl->buffer = (BYTE *)malloc(ctrl->bufsize);
}
// Set transfer amount
ctrl->length = ctrl->cmd[6];
ctrl->length <<= 8;
ctrl->length |= ctrl->cmd[7];
ctrl->length <<= 8;
ctrl->length |= ctrl->cmd[8];
if (ctrl->length <= 0) {
// Failure (Error)
controller->Error();
return;
}
// Set next block
ctrl->blocks = 1;
ctrl->next = 1;
controller->DataOut();
}
int SCSIBR::GetMacAddr(BYTE *mac)
{
memcpy(mac, mac_addr, 6);
return 6;
}
void SCSIBR::SetMacAddr(BYTE *mac)
{
memcpy(mac_addr, mac, 6);
}
void SCSIBR::ReceivePacket()
{
static const BYTE bcast_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
assert(tap);
// previous packet has not been received
if (packet_enable) {
return;
}
// Receive packet
packet_len = tap->Rx(packet_buf);
// Check if received packet
if (memcmp(packet_buf, mac_addr, 6) != 0) {
if (memcmp(packet_buf, bcast_addr, 6) != 0) {
packet_len = 0;
return;
}
}
// Discard if it exceeds the buffer size
if (packet_len > 2048) {
packet_len = 0;
return;
}
// Store in receive buffer
if (packet_len > 0) {
packet_enable = true;
}
}
void SCSIBR::GetPacketBuf(BYTE *buf)
{
assert(tap);
// Size limit
int len = packet_len;
if (len > 2048) {
len = 2048;
}
// Copy
memcpy(buf, packet_buf, len);
// Received
packet_enable = false;
}
void SCSIBR::SendPacket(BYTE *buf, int len)
{
assert(tap);
tap->Tx(buf, len);
}
//---------------------------------------------------------------------------
//
// $40 - Device Boot
//
//---------------------------------------------------------------------------
void SCSIBR::FS_InitDevice(BYTE *buf)
{
fs->Reset();
fsresult = fs->InitDevice((Human68k::argument_t*)buf);
}
//---------------------------------------------------------------------------
//
// $41 - Directory Check
//
//---------------------------------------------------------------------------
void SCSIBR::FS_CheckDir(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
int i = sizeof(DWORD);
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
i += sizeof(Human68k::namests_t);
fsresult = fs->CheckDir(nUnit, pNamests);
}
//---------------------------------------------------------------------------
//
// $42 - Create Directory
//
//---------------------------------------------------------------------------
void SCSIBR::FS_MakeDir(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
int i = sizeof(DWORD);
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
i += sizeof(Human68k::namests_t);
fsresult = fs->MakeDir(nUnit, pNamests);
}
//---------------------------------------------------------------------------
//
// $43 - Remove Directory
//
//---------------------------------------------------------------------------
void SCSIBR::FS_RemoveDir(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
int i = sizeof(DWORD);
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
i += sizeof(Human68k::namests_t);
fsresult = fs->RemoveDir(nUnit, pNamests);
}
//---------------------------------------------------------------------------
//
// $44 - Rename
//
//---------------------------------------------------------------------------
void SCSIBR::FS_Rename(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
int i = sizeof(DWORD);
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
i += sizeof(Human68k::namests_t);
Human68k::namests_t *pNamestsNew = (Human68k::namests_t*)&buf[i];
i += sizeof(Human68k::namests_t);
fsresult = fs->Rename(nUnit, pNamests, pNamestsNew);
}
//---------------------------------------------------------------------------
//
// $45 - Delete File
//
//---------------------------------------------------------------------------
void SCSIBR::FS_Delete(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
int i = sizeof(DWORD);
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
i += sizeof(Human68k::namests_t);
fsresult = fs->Delete(nUnit, pNamests);
}
//---------------------------------------------------------------------------
//
// $46 - Get / Set file attributes
//
//---------------------------------------------------------------------------
void SCSIBR::FS_Attribute(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
int i = sizeof(DWORD);
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
i += sizeof(Human68k::namests_t);
dp = (DWORD*)&buf[i];
DWORD nHumanAttribute = ntohl(*dp);
i += sizeof(DWORD);
fsresult = fs->Attribute(nUnit, pNamests, nHumanAttribute);
}
//---------------------------------------------------------------------------
//
// $47 - File Search
//
//---------------------------------------------------------------------------
void SCSIBR::FS_Files(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
int i = sizeof(DWORD);
dp = (DWORD*)&buf[i];
DWORD nKey = ntohl(*dp);
i += sizeof(DWORD);
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
i += sizeof(Human68k::namests_t);
Human68k::files_t *files = (Human68k::files_t*)&buf[i];
i += sizeof(Human68k::files_t);
files->sector = ntohl(files->sector);
files->offset = ntohs(files->offset);
files->time = ntohs(files->time);
files->date = ntohs(files->date);
files->size = ntohl(files->size);
fsresult = fs->Files(nUnit, nKey, pNamests, files);
files->sector = htonl(files->sector);
files->offset = htons(files->offset);
files->time = htons(files->time);
files->date = htons(files->date);
files->size = htonl(files->size);
i = 0;
memcpy(&fsout[i], files, sizeof(Human68k::files_t));
i += sizeof(Human68k::files_t);
fsoutlen = i;
}
//---------------------------------------------------------------------------
//
// $48 - File next search
//
//---------------------------------------------------------------------------
void SCSIBR::FS_NFiles(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
int i = sizeof(DWORD);
dp = (DWORD*)&buf[i];
DWORD nKey = ntohl(*dp);
i += sizeof(DWORD);
Human68k::files_t *files = (Human68k::files_t*)&buf[i];
i += sizeof(Human68k::files_t);
files->sector = ntohl(files->sector);
files->offset = ntohs(files->offset);
files->time = ntohs(files->time);
files->date = ntohs(files->date);
files->size = ntohl(files->size);
fsresult = fs->NFiles(nUnit, nKey, files);
files->sector = htonl(files->sector);
files->offset = htons(files->offset);
files->time = htons(files->time);
files->date = htons(files->date);
files->size = htonl(files->size);
i = 0;
memcpy(&fsout[i], files, sizeof(Human68k::files_t));
i += sizeof(Human68k::files_t);
fsoutlen = i;
}
//---------------------------------------------------------------------------
//
// $49 - File Creation
//
//---------------------------------------------------------------------------
void SCSIBR::FS_Create(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
int i = sizeof(DWORD);
dp = (DWORD*)&buf[i];
DWORD nKey = ntohl(*dp);
i += sizeof(DWORD);
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
i += sizeof(Human68k::namests_t);
Human68k::fcb_t *pFcb = (Human68k::fcb_t*)&buf[i];
i += sizeof(Human68k::fcb_t);
dp = (DWORD*)&buf[i];
DWORD nAttribute = ntohl(*dp);
i += sizeof(DWORD);
BOOL *bp = (BOOL*)&buf[i];
DWORD bForce = ntohl(*bp);
i += sizeof(BOOL);
pFcb->fileptr = ntohl(pFcb->fileptr);
pFcb->mode = ntohs(pFcb->mode);
pFcb->time = ntohs(pFcb->time);
pFcb->date = ntohs(pFcb->date);
pFcb->size = ntohl(pFcb->size);
fsresult = fs->Create(nUnit, nKey, pNamests, pFcb, nAttribute, bForce);
pFcb->fileptr = htonl(pFcb->fileptr);
pFcb->mode = htons(pFcb->mode);
pFcb->time = htons(pFcb->time);
pFcb->date = htons(pFcb->date);
pFcb->size = htonl(pFcb->size);
i = 0;
memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t));
i += sizeof(Human68k::fcb_t);
fsoutlen = i;
}
//---------------------------------------------------------------------------
//
// $4A - Open File
//
//---------------------------------------------------------------------------
void SCSIBR::FS_Open(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
int i = sizeof(DWORD);
dp = (DWORD*)&buf[i];
DWORD nKey = ntohl(*dp);
i += sizeof(DWORD);
Human68k::namests_t *pNamests = (Human68k::namests_t*)&buf[i];
i += sizeof(Human68k::namests_t);
Human68k::fcb_t *pFcb = (Human68k::fcb_t*)&buf[i];
i += sizeof(Human68k::fcb_t);
pFcb->fileptr = ntohl(pFcb->fileptr);
pFcb->mode = ntohs(pFcb->mode);
pFcb->time = ntohs(pFcb->time);
pFcb->date = ntohs(pFcb->date);
pFcb->size = ntohl(pFcb->size);
fsresult = fs->Open(nUnit, nKey, pNamests, pFcb);
pFcb->fileptr = htonl(pFcb->fileptr);
pFcb->mode = htons(pFcb->mode);
pFcb->time = htons(pFcb->time);
pFcb->date = htons(pFcb->date);
pFcb->size = htonl(pFcb->size);
i = 0;
memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t));
i += sizeof(Human68k::fcb_t);
fsoutlen = i;
}
//---------------------------------------------------------------------------
//
// $4B - Close File
//
//---------------------------------------------------------------------------
void SCSIBR::FS_Close(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
int i = sizeof(DWORD);
dp = (DWORD*)&buf[i];
DWORD nKey = ntohl(*dp);
i += sizeof(DWORD);
Human68k::fcb_t *pFcb = (Human68k::fcb_t*)&buf[i];
i += sizeof(Human68k::fcb_t);
pFcb->fileptr = ntohl(pFcb->fileptr);
pFcb->mode = ntohs(pFcb->mode);
pFcb->time = ntohs(pFcb->time);
pFcb->date = ntohs(pFcb->date);
pFcb->size = ntohl(pFcb->size);
fsresult = fs->Close(nUnit, nKey, pFcb);
pFcb->fileptr = htonl(pFcb->fileptr);
pFcb->mode = htons(pFcb->mode);
pFcb->time = htons(pFcb->time);
pFcb->date = htons(pFcb->date);
pFcb->size = htonl(pFcb->size);
i = 0;
memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t));
i += sizeof(Human68k::fcb_t);
fsoutlen = i;
}
//---------------------------------------------------------------------------
//
// $4C - Read File
//
//---------------------------------------------------------------------------
void SCSIBR::FS_Read(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nKey = ntohl(*dp);
int i = sizeof(DWORD);
Human68k::fcb_t *pFcb = (Human68k::fcb_t*)&buf[i];
i += sizeof(Human68k::fcb_t);
dp = (DWORD*)&buf[i];
DWORD nSize = ntohl(*dp);
i += sizeof(DWORD);
pFcb->fileptr = ntohl(pFcb->fileptr);
pFcb->mode = ntohs(pFcb->mode);
pFcb->time = ntohs(pFcb->time);
pFcb->date = ntohs(pFcb->date);
pFcb->size = ntohl(pFcb->size);
fsresult = fs->Read(nKey, pFcb, fsopt, nSize);
pFcb->fileptr = htonl(pFcb->fileptr);
pFcb->mode = htons(pFcb->mode);
pFcb->time = htons(pFcb->time);
pFcb->date = htons(pFcb->date);
pFcb->size = htonl(pFcb->size);
i = 0;
memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t));
i += sizeof(Human68k::fcb_t);
fsoutlen = i;
fsoptlen = fsresult;
}
//---------------------------------------------------------------------------
//
// $4D - Write file
//
//---------------------------------------------------------------------------
void SCSIBR::FS_Write(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nKey = ntohl(*dp);
int i = sizeof(DWORD);
Human68k::fcb_t *pFcb = (Human68k::fcb_t*)&buf[i];
i += sizeof(Human68k::fcb_t);
dp = (DWORD*)&buf[i];
DWORD nSize = ntohl(*dp);
i += sizeof(DWORD);
pFcb->fileptr = ntohl(pFcb->fileptr);
pFcb->mode = ntohs(pFcb->mode);
pFcb->time = ntohs(pFcb->time);
pFcb->date = ntohs(pFcb->date);
pFcb->size = ntohl(pFcb->size);
fsresult = fs->Write(nKey, pFcb, fsopt, nSize);
pFcb->fileptr = htonl(pFcb->fileptr);
pFcb->mode = htons(pFcb->mode);
pFcb->time = htons(pFcb->time);
pFcb->date = htons(pFcb->date);
pFcb->size = htonl(pFcb->size);
i = 0;
memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t));
i += sizeof(Human68k::fcb_t);
fsoutlen = i;
}
//---------------------------------------------------------------------------
//
// $4E - Seek file
//
//---------------------------------------------------------------------------
void SCSIBR::FS_Seek(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nKey = ntohl(*dp);
int i = sizeof(DWORD);
Human68k::fcb_t *pFcb = (Human68k::fcb_t*)&buf[i];
i += sizeof(Human68k::fcb_t);
dp = (DWORD*)&buf[i];
DWORD nMode = ntohl(*dp);
i += sizeof(DWORD);
int *ip = (int*)&buf[i];
int nOffset = ntohl(*ip);
i += sizeof(int);
pFcb->fileptr = ntohl(pFcb->fileptr);
pFcb->mode = ntohs(pFcb->mode);
pFcb->time = ntohs(pFcb->time);
pFcb->date = ntohs(pFcb->date);
pFcb->size = ntohl(pFcb->size);
fsresult = fs->Seek(nKey, pFcb, nMode, nOffset);
pFcb->fileptr = htonl(pFcb->fileptr);
pFcb->mode = htons(pFcb->mode);
pFcb->time = htons(pFcb->time);
pFcb->date = htons(pFcb->date);
pFcb->size = htonl(pFcb->size);
i = 0;
memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t));
i += sizeof(Human68k::fcb_t);
fsoutlen = i;
}
//---------------------------------------------------------------------------
//
// $4F - File Timestamp Get / Set
//
//---------------------------------------------------------------------------
void SCSIBR::FS_TimeStamp(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
int i = sizeof(DWORD);
dp = (DWORD*)&buf[i];
DWORD nKey = ntohl(*dp);
i += sizeof(DWORD);
Human68k::fcb_t *pFcb = (Human68k::fcb_t*)&buf[i];
i += sizeof(Human68k::fcb_t);
dp = (DWORD*)&buf[i];
DWORD nHumanTime = ntohl(*dp);
i += sizeof(DWORD);
pFcb->fileptr = ntohl(pFcb->fileptr);
pFcb->mode = ntohs(pFcb->mode);
pFcb->time = ntohs(pFcb->time);
pFcb->date = ntohs(pFcb->date);
pFcb->size = ntohl(pFcb->size);
fsresult = fs->TimeStamp(nUnit, nKey, pFcb, nHumanTime);
pFcb->fileptr = htonl(pFcb->fileptr);
pFcb->mode = htons(pFcb->mode);
pFcb->time = htons(pFcb->time);
pFcb->date = htons(pFcb->date);
pFcb->size = htonl(pFcb->size);
i = 0;
memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t));
i += sizeof(Human68k::fcb_t);
fsoutlen = i;
}
//---------------------------------------------------------------------------
//
// $50 - Get Capacity
//
//---------------------------------------------------------------------------
void SCSIBR::FS_GetCapacity(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
Human68k::capacity_t cap;
fsresult = fs->GetCapacity(nUnit, &cap);
cap.freearea = htons(cap.freearea);
cap.clusters = htons(cap.clusters);
cap.sectors = htons(cap.sectors);
cap.bytes = htons(cap.bytes);
memcpy(fsout, &cap, sizeof(Human68k::capacity_t));
fsoutlen = sizeof(Human68k::capacity_t);
}
//---------------------------------------------------------------------------
//
// $51 - Drive status inspection/control
//
//---------------------------------------------------------------------------
void SCSIBR::FS_CtrlDrive(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
int i = sizeof(DWORD);
Human68k::ctrldrive_t *pCtrlDrive = (Human68k::ctrldrive_t*)&buf[i];
fsresult = fs->CtrlDrive(nUnit, pCtrlDrive);
memcpy(fsout, pCtrlDrive, sizeof(Human68k::ctrldrive_t));
fsoutlen = sizeof(Human68k::ctrldrive_t);
}
//---------------------------------------------------------------------------
//
// $52 - Get DPB
//
//---------------------------------------------------------------------------
void SCSIBR::FS_GetDPB(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
Human68k::dpb_t dpb;
fsresult = fs->GetDPB(nUnit, &dpb);
dpb.sector_size = htons(dpb.sector_size);
dpb.fat_sector = htons(dpb.fat_sector);
dpb.file_max = htons(dpb.file_max);
dpb.data_sector = htons(dpb.data_sector);
dpb.cluster_max = htons(dpb.cluster_max);
dpb.root_sector = htons(dpb.root_sector);
memcpy(fsout, &dpb, sizeof(Human68k::dpb_t));
fsoutlen = sizeof(Human68k::dpb_t);
}
//---------------------------------------------------------------------------
//
// $53 - Read Sector
//
//---------------------------------------------------------------------------
void SCSIBR::FS_DiskRead(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
int i = sizeof(DWORD);
dp = (DWORD*)&buf[i];
DWORD nSector = ntohl(*dp);
i += sizeof(DWORD);
dp = (DWORD*)&buf[i];
DWORD nSize = ntohl(*dp);
i += sizeof(DWORD);
fsresult = fs->DiskRead(nUnit, fsout, nSector, nSize);
fsoutlen = 0x200;
}
//---------------------------------------------------------------------------
//
// $54 - Write Sector
//
//---------------------------------------------------------------------------
void SCSIBR::FS_DiskWrite(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
fsresult = fs->DiskWrite(nUnit);
}
//---------------------------------------------------------------------------
//
// $55 - IOCTRL
//
//---------------------------------------------------------------------------
void SCSIBR::FS_Ioctrl(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
int i = sizeof(DWORD);
dp = (DWORD*)&buf[i];
DWORD nFunction = ntohl(*dp);
i += sizeof(DWORD);
Human68k::ioctrl_t *pIoctrl = (Human68k::ioctrl_t*)&buf[i];
i += sizeof(Human68k::ioctrl_t);
switch (nFunction) {
case 2:
case (DWORD)-2:
pIoctrl->param = htonl(pIoctrl->param);
break;
}
fsresult = fs->Ioctrl(nUnit, nFunction, pIoctrl);
switch (nFunction) {
case 0:
pIoctrl->media = htons(pIoctrl->media);
break;
case 1:
case (DWORD)-3:
pIoctrl->param = htonl(pIoctrl->param);
break;
}
i = 0;
memcpy(&fsout[i], pIoctrl, sizeof(Human68k::ioctrl_t));
i += sizeof(Human68k::ioctrl_t);
fsoutlen = i;
}
//---------------------------------------------------------------------------
//
// $56 - Flush
//
//---------------------------------------------------------------------------
void SCSIBR::FS_Flush(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
fsresult = fs->Flush(nUnit);
}
//---------------------------------------------------------------------------
//
// $57 - Check Media
//
//---------------------------------------------------------------------------
void SCSIBR::FS_CheckMedia(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
fsresult = fs->CheckMedia(nUnit);
}
//---------------------------------------------------------------------------
//
// $58 - Lock
//
//---------------------------------------------------------------------------
void SCSIBR::FS_Lock(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
DWORD nUnit = ntohl(*dp);
fsresult = fs->Lock(nUnit);
}
//---------------------------------------------------------------------------
//
// Read Filesystem (result code)
//
//---------------------------------------------------------------------------
int SCSIBR::ReadFsResult(BYTE *buf)
{
DWORD *dp = (DWORD*)buf;
*dp = htonl(fsresult);
return sizeof(DWORD);
}
//---------------------------------------------------------------------------
//
// Read Filesystem (return data)
//
//---------------------------------------------------------------------------
int SCSIBR::ReadFsOut(BYTE *buf)
{
memcpy(buf, fsout, fsoutlen);
return fsoutlen;
}
//---------------------------------------------------------------------------
//
// Read file system (return option data)
//
//---------------------------------------------------------------------------
int SCSIBR::ReadFsOpt(BYTE *buf)
{
memcpy(buf, fsopt, fsoptlen);
return fsoptlen;
}
//---------------------------------------------------------------------------
//
// Write Filesystem
//
//---------------------------------------------------------------------------
void SCSIBR::WriteFs(int func, BYTE *buf)
{
fsresult = FS_FATAL_INVALIDCOMMAND;
fsoutlen = 0;
fsoptlen = 0;
func &= 0x1f;
switch (func) {
case 0x00: return FS_InitDevice(buf); // $40 - start device
case 0x01: return FS_CheckDir(buf); // $41 - directory check
case 0x02: return FS_MakeDir(buf); // $42 - create directory
case 0x03: return FS_RemoveDir(buf); // $43 - remove directory
case 0x04: return FS_Rename(buf); // $44 - change file name
case 0x05: return FS_Delete(buf); // $45 - delete file
case 0x06: return FS_Attribute(buf); // $46 - Get/set file attribute
case 0x07: return FS_Files(buf); // $47 - file search
case 0x08: return FS_NFiles(buf); // $48 - next file search
case 0x09: return FS_Create(buf); // $49 - create file
case 0x0A: return FS_Open(buf); // $4A - File open
case 0x0B: return FS_Close(buf); // $4B - File close
case 0x0C: return FS_Read(buf); // $4C - read file
case 0x0D: return FS_Write(buf); // $4D - write file
case 0x0E: return FS_Seek(buf); // $4E - File seek
case 0x0F: return FS_TimeStamp(buf); // $4F - Get/set file modification time
case 0x10: return FS_GetCapacity(buf); // $50 - get capacity
case 0x11: return FS_CtrlDrive(buf); // $51 - Drive control/state check
case 0x12: return FS_GetDPB(buf); // $52 - Get DPB
case 0x13: return FS_DiskRead(buf); // $53 - read sector
case 0x14: return FS_DiskWrite(buf); // $54 - write sector
case 0x15: return FS_Ioctrl(buf); // $55 - IOCTRL
case 0x16: return FS_Flush(buf); // $56 - flush
case 0x17: return FS_CheckMedia(buf); // $57 - check media exchange
case 0x18: return FS_Lock(buf); // $58 - exclusive control
}
}
//---------------------------------------------------------------------------
//
// File system write (input option data)
//
//---------------------------------------------------------------------------
void SCSIBR::WriteFsOpt(BYTE *buf, int num)
{
memcpy(fsopt, buf, num);
}