RASCSI/src_old/raspberrypi/devices/scsi_host_bridge.cpp

1185 lines
28 KiB
C++
Raw Normal View History

2023-01-09 02:04:49 +00:00
//---------------------------------------------------------------------------
//
// 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);
}