Initial tape and magneto-optical support

This commit is contained in:
Michael McMaster 2015-09-06 15:15:41 +10:00
parent 9f5624ddd7
commit 6a7207c092
10 changed files with 219 additions and 46 deletions

View File

@ -277,50 +277,43 @@ int scsiCDRomCommand()
int commandHandled = 1;
uint8 command = scsiDev.cdb[0];
if (scsiDev.target->cfg->deviceType == CONFIG_OPTICAL)
if (command == 0x43)
{
if (command == 0x43)
{
// CD-ROM Read TOC
int MSF = scsiDev.cdb[1] & 0x02 ? 1 : 0;
uint8_t track = scsiDev.cdb[6];
uint16_t allocationLength =
(((uint32_t) scsiDev.cdb[7]) << 8) +
scsiDev.cdb[8];
// CD-ROM Read TOC
int MSF = scsiDev.cdb[1] & 0x02 ? 1 : 0;
uint8_t track = scsiDev.cdb[6];
uint16_t allocationLength =
(((uint32_t) scsiDev.cdb[7]) << 8) +
scsiDev.cdb[8];
// Reject MMC commands for now, otherwise the TOC data format
// won't be understood.
// The "format" field is reserved for SCSI-2
uint8_t format = scsiDev.cdb[2] & 0x0F;
switch (format)
// Reject MMC commands for now, otherwise the TOC data format
// won't be understood.
// The "format" field is reserved for SCSI-2
uint8_t format = scsiDev.cdb[2] & 0x0F;
switch (format)
{
case 0: doReadTOC(MSF, track, allocationLength); break; // SCSI-2
case 1: doReadSessionInfo(MSF, allocationLength); break; // MMC2
case 2: doReadFullTOC(0, track, allocationLength); break; // MMC2
case 3: doReadFullTOC(1, track, allocationLength); break; // MMC2
default:
{
case 0: doReadTOC(MSF, track, allocationLength); break; // SCSI-2
case 1: doReadSessionInfo(MSF, allocationLength); break; // MMC2
case 2: doReadFullTOC(0, track, allocationLength); break; // MMC2
case 3: doReadFullTOC(1, track, allocationLength); break; // MMC2
default:
{
scsiDev.status = CHECK_CONDITION;
scsiDev.target->sense.code = ILLEGAL_REQUEST;
scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
scsiDev.phase = STATUS;
}
scsiDev.status = CHECK_CONDITION;
scsiDev.target->sense.code = ILLEGAL_REQUEST;
scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
scsiDev.phase = STATUS;
}
}
else if (command == 0x44)
{
// CD-ROM Read Header
int MSF = scsiDev.cdb[1] & 0x02 ? 1 : 0;
uint32_t lba = 0; // IGNORED for now
uint16_t allocationLength =
(((uint32_t) scsiDev.cdb[7]) << 8) +
scsiDev.cdb[8];
doReadHeader(MSF, lba, allocationLength);
}
else
{
commandHandled = 0;
}
}
else if (command == 0x44)
{
// CD-ROM Read Header
int MSF = scsiDev.cdb[1] & 0x02 ? 1 : 0;
uint32_t lba = 0; // IGNORED for now
uint16_t allocationLength =
(((uint32_t) scsiDev.cdb[7]) << 8) +
scsiDev.cdb[8];
doReadHeader(MSF, lba, allocationLength);
}
else
{

View File

@ -203,6 +203,16 @@ void scsiInquiry()
scsiDev.data[1] |= 0x80; // Removable bit.
break;
case CONFIG_SEQUENTIAL:
scsiDev.data[0] = 0x01; // device type
scsiDev.data[1] |= 0x80; // Removable bit.
break;
case CONFIG_MO:
scsiDev.data[0] = 0x07; // device type
scsiDev.data[1] |= 0x80; // Removable bit.
break;
case CONFIG_FLOPPY_14MB:
case CONFIG_REMOVEABLE:
scsiDev.data[1] |= 0x80; // Removable bit.

43
software/SCSI2SD/src/mo.c Normal file
View File

@ -0,0 +1,43 @@
// Copyright (C) 2015 Michael McMaster <michael@codesrc.com>
//
// This file is part of SCSI2SD.
//
// SCSI2SD is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// SCSI2SD is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
#pragma GCC push_options
#pragma GCC optimize("-flto")
#include "device.h"
#include "scsi.h"
#include "config.h"
#include "mo.h"
// Handle magneto-optical scsi device commands
int scsiMOCommand()
{
int commandHandled = 0;
uint8 command = scsiDev.cdb[0];
if ((command == 0x2C) || // ERASE(10)
(command == 0xAC)) // ERASE(12)
{
// TODO consider sending an erase command to the SD card.
commandHandled = 1;
}
return commandHandled;
}
#pragma GCC pop_options

22
software/SCSI2SD/src/mo.h Normal file
View File

@ -0,0 +1,22 @@
// Copyright (C) 2015 Michael McMaster <michael@codesrc.com>
//
// This file is part of SCSI2SD.
//
// SCSI2SD is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// SCSI2SD is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
#ifndef MO_H
#define MO_H
int scsiMOCommand(void);
#endif

View File

@ -161,6 +161,22 @@ static const uint8 ControlModePage[] =
0x00, 0x00 // AEN holdoff period.
};
static const uint8_t SequentialDeviceConfigPage[] =
{
0x10, // page code
0x0E, // Page length
0x00, // CAP, CAF, Active Format
0x00, // Active partition
0x00, // Write buffer full ratio
0x00, // Read buffer empty ratio
0x00,0x01, // Write delay time, in 100ms units
0x00, // Default gap size
0x10, // auto-generation of default eod (end of data)
0x00,0x00,0x00 // buffer-size at early warning
0x00, // No data compression
0x00 // reserved
};
// Allow Apple 68k Drive Setup to format this drive.
// Code
static const uint8 AppleVendorPage[] =
@ -218,6 +234,17 @@ static void doModeSense(
density = 0x01; // User data only, 2048bytes per sector.
break;
case CONFIG_SEQUENTIAL:
mediumType = 0; // reserved
deviceSpecificParam =
(blockDev.state & DISK_WP) ? 0x80 : 0;
density = 0x13; // DAT Data Storage, X3B5/88-185A
break;
case CONFIG_MO:
TODO
break;
};
scsiDev.data[idx++] = mediumType;
@ -400,6 +427,18 @@ static void doModeSense(
idx += sizeof(ControlModePage);
}
if ((scsiDev.target->cfg->deviceType == CONFIG_SEQUENTIAL) &&
(pageCode == 0x10 || pageCode == 0x3F))
{
pageFound = 1;
pageIn(
pc,
idx,
SequentialDeviceConfigPage,
sizeof(SequentialDeviceConfigPage));
idx += sizeof(SequentialDeviceConfigPage);
}
if ((
(scsiDev.target->cfg->quirks == CONFIG_QUIRKS_APPLE) ||
(idx + sizeof(AppleVendorPage) <= allocLength)

View File

@ -264,6 +264,7 @@ static void process_Command()
control = scsiDev.cdb[scsiDev.cdbLen - 1];
scsiDev.cmdCount++;
TargetConfig* cfg = scsiDev.target->cfg;
if (unlikely(scsiDev.resetFlag))
{
@ -273,7 +274,7 @@ static void process_Command()
return;
}
else if (scsiDev.parityError &&
(scsiDev.target->cfg->flags & CONFIG_ENABLE_PARITY) &&
(cfg->flags & CONFIG_ENABLE_PARITY) &&
(scsiDev.compatMode >= COMPAT_SCSI2))
{
scsiDev.target->sense.code = ABORTED_COMMAND;
@ -326,7 +327,7 @@ static void process_Command()
// on receiving the unit attention response on boot, thus
// triggering another unit attention condition.
else if (scsiDev.target->unitAttention &&
(scsiDev.target->cfg->flags & CONFIG_ENABLE_UNIT_ATTENTION))
(cfg->flags & CONFIG_ENABLE_UNIT_ATTENTION))
{
scsiDev.target->sense.code = UNIT_ATTENTION;
scsiDev.target->sense.asc = scsiDev.target->unitAttention;
@ -352,6 +353,14 @@ static void process_Command()
{
enter_Status(CONFLICT);
}
// Handle odd device types first that may override basic read and
// write commands. Will fall-through to generic disk handling.
else if (((cfg->deviceType == CONFIG_OPTICAL) && scsiCDRomCommand()) ||
((cfg->deviceType == CONFIG_SEQUENTIAL) && scsiTapeCommand()) ||
((cfg->deviceType == CONFIG_MO) && scsiMOCommand()))
{
// Already handled.
}
else if (scsiDiskCommand())
{
// Already handled.
@ -374,9 +383,7 @@ static void process_Command()
{
scsiReadBuffer();
}
else if (
!scsiCDRomCommand() &&
!scsiModeCommand())
else if (!scsiModeCommand())
{
scsiDev.target->sense.code = ILLEGAL_REQUEST;
scsiDev.target->sense.asc = INVALID_COMMAND_OPERATION_CODE;

View File

@ -0,0 +1,33 @@
// Copyright (C) 2015 Michael McMaster <michael@codesrc.com>
//
// This file is part of SCSI2SD.
//
// SCSI2SD is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// SCSI2SD is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
#pragma GCC push_options
#pragma GCC optimize("-flto")
#include "device.h"
#include "scsi.h"
#include "config.h"
#include "tape.h"
// Handle sequential scsi device commands
int scsiTapeCommand()
{
// TODO handle tape-specific read/write commands and return 1
return 0;
}
#pragma GCC pop_options

View File

@ -0,0 +1,22 @@
// Copyright (C) 2015 Michael McMaster <michael@codesrc.com>
//
// This file is part of SCSI2SD.
//
// SCSI2SD is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// SCSI2SD is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
#ifndef TAPE_H
#define TAPE_H
int scsiTapeCommand(void);
#endif

View File

@ -93,7 +93,10 @@ typedef enum
CONFIG_FIXED,
CONFIG_REMOVEABLE,
CONFIG_OPTICAL,
CONFIG_FLOPPY_14MB
CONFIG_FLOPPY_14MB,
CONFIG_MO,
CONFIG_SEQUENTIAL
} CONFIG_TYPE;
typedef enum

View File

@ -109,7 +109,8 @@ TargetPanel::TargetPanel(wxWindow* parent, const TargetConfig& initialConfig) :
wxT("Hard Drive"),
wxT("Removable"),
wxT("CDROM"),
wxT("3.5\" Floppy")
wxT("3.5\" Floppy"),
wxT("Magneto optical")
};
myDeviceTypeCtrl =
new wxChoice(