mirror of
https://github.com/fhgwright/SCSI2SD.git
synced 2025-04-10 01:37:07 +00:00
V4.7 release fixes
This commit is contained in:
parent
ecdf21796a
commit
c75fbc8e6e
12
CHANGELOG
12
CHANGELOG
@ -1,5 +1,15 @@
|
||||
2016xxxx 4.x
|
||||
20170312 4.7
|
||||
- Fix bug in SCSI Inquiry command for SCSI2 hosts
|
||||
- Added OMTI host quirks mode
|
||||
- Fix for booting from early Mac Plus ROMS
|
||||
- Performance fix when SCSI2 mode is enabled. Some users may need
|
||||
to disable SCSI2 mode if it was incorrectly enabled previously.
|
||||
- Added support for configurable mode pages
|
||||
- Fix for exporting selectionDelay/startupDelay parameters to XML
|
||||
via scsi2sd-util
|
||||
- scsi2sd-util is now built with libudev1 on Linux, as all distros have
|
||||
moved to this version. Users on older Linux distributions will need to
|
||||
compile from source.
|
||||
|
||||
20160111 4.6
|
||||
- Fixed bug when using sector size that isn't a multiple of 4
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static const uint16_t FIRMWARE_VERSION = 0x0460;
|
||||
static const uint16_t FIRMWARE_VERSION = 0x0470;
|
||||
|
||||
// 1 flash row
|
||||
static const uint8_t DEFAULT_CONFIG[256] =
|
||||
@ -418,13 +418,24 @@ void configSave(int scsiId, uint16_t bytesPerSector)
|
||||
|
||||
const TargetConfig* getConfigByIndex(int i)
|
||||
{
|
||||
size_t row = SCSI_CONFIG_0_ROW + (i * SCSI_CONFIG_ROWS);
|
||||
return (const TargetConfig*)
|
||||
(
|
||||
CY_FLASH_BASE +
|
||||
(CY_FLASH_SIZEOF_ARRAY * (size_t) SCSI_CONFIG_ARRAY) +
|
||||
(CY_FLASH_SIZEOF_ROW * row)
|
||||
);
|
||||
if (i <= 3)
|
||||
{
|
||||
size_t row = SCSI_CONFIG_0_ROW + (i * SCSI_CONFIG_ROWS);
|
||||
return (const TargetConfig*)
|
||||
(
|
||||
CY_FLASH_BASE +
|
||||
(CY_FLASH_SIZEOF_ARRAY * (size_t) SCSI_CONFIG_ARRAY) +
|
||||
(CY_FLASH_SIZEOF_ROW * row)
|
||||
);
|
||||
} else {
|
||||
size_t row = SCSI_CONFIG_4_ROW + ((i-4) * SCSI_CONFIG_ROWS);
|
||||
return (const TargetConfig*)
|
||||
(
|
||||
CY_FLASH_BASE +
|
||||
(CY_FLASH_SIZEOF_ARRAY * (size_t) SCSI_CONFIG_ARRAY) +
|
||||
(CY_FLASH_SIZEOF_ROW * row)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const TargetConfig* getConfigById(int scsiId)
|
||||
|
@ -1,258 +1,267 @@
|
||||
// Copyright (C) 2013 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 "inquiry.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static uint8 StandardResponse[] =
|
||||
{
|
||||
0x00, // "Direct-access device". AKA standard hard disk
|
||||
0x00, // device type modifier
|
||||
0x02, // Complies with ANSI SCSI-2.
|
||||
0x01, // Response format is compatible with the old CCS format.
|
||||
0x1f, // standard length.
|
||||
0, 0, // Reserved
|
||||
0x08 // Enable linked commands
|
||||
};
|
||||
// Vendor set by config 'c','o','d','e','s','r','c',' ',
|
||||
// prodId set by config'S','C','S','I','2','S','D',' ',' ',' ',' ',' ',' ',' ',' ',' ',
|
||||
// Revision set by config'2','.','0','a'
|
||||
|
||||
/* For reference, here's a dump from an Apple branded 500Mb drive from 1994.
|
||||
$ sudo sg_inq -H /dev/sdd --len 255
|
||||
standard INQUIRY:
|
||||
00 00 00 02 01 31 00 00 18 51 55 41 4e 54 55 4d 20 ....1...QUANTUM
|
||||
10 4c 50 53 32 37 30 20 20 20 20 20 20 20 20 20 20 LPS270
|
||||
20 30 39 30 30 00 00 00 d9 b0 27 34 01 04 b3 01 1b 0900.....'4.....
|
||||
30 07 00 a0 00 00 ff ......
|
||||
Vendor identification: QUANTUM
|
||||
Product identification: LPS270
|
||||
Product revision level: 0900
|
||||
*/
|
||||
|
||||
|
||||
static const uint8 SupportedVitalPages[] =
|
||||
{
|
||||
0x00, // "Direct-access device". AKA standard hard disk
|
||||
0x00, // Page Code
|
||||
0x00, // Reserved
|
||||
0x04, // Page length
|
||||
0x00, // Support "Supported vital product data pages"
|
||||
0x80, // Support "Unit serial number page"
|
||||
0x81, // Support "Implemented operating definition page"
|
||||
0x82 // Support "ASCII Implemented operating definition page"
|
||||
};
|
||||
|
||||
static const uint8 UnitSerialNumber[] =
|
||||
{
|
||||
0x00, // "Direct-access device". AKA standard hard disk
|
||||
0x80, // Page Code
|
||||
0x00, // Reserved
|
||||
0x10, // Page length
|
||||
'c','o','d','e','s','r','c','-','1','2','3','4','5','6','7','8'
|
||||
};
|
||||
|
||||
static const uint8 ImpOperatingDefinition[] =
|
||||
{
|
||||
0x00, // "Direct-access device". AKA standard hard disk
|
||||
0x81, // Page Code
|
||||
0x00, // Reserved
|
||||
0x03, // Page length
|
||||
0x03, // Current: SCSI-2 operating definition
|
||||
0x03, // Default: SCSI-2 operating definition
|
||||
0x03 // Supported (list): SCSI-2 operating definition.
|
||||
};
|
||||
|
||||
static const uint8 AscImpOperatingDefinition[] =
|
||||
{
|
||||
0x00, // "Direct-access device". AKA standard hard disk
|
||||
0x82, // Page Code
|
||||
0x00, // Reserved
|
||||
0x07, // Page length
|
||||
0x06, // Ascii length
|
||||
'S','C','S','I','-','2'
|
||||
};
|
||||
|
||||
static void useCustomVPD(const TargetConfig* cfg, int pageCode)
|
||||
{
|
||||
int cfgIdx = 0;
|
||||
int found = 0;
|
||||
while ((cfgIdx < sizeof(cfg->vpd) - 4) &&
|
||||
(cfg->vpd[cfgIdx + 3] != 0)
|
||||
)
|
||||
{
|
||||
int pageSize = cfg->vpd[cfgIdx + 3] + 4;
|
||||
int dataPageCode = cfg->vpd[cfgIdx + 1];
|
||||
if (dataPageCode == pageCode)
|
||||
{
|
||||
memcpy(scsiDev.data, &(cfg->vpd[cfgIdx]), pageSize);
|
||||
scsiDev.dataLen = pageSize;
|
||||
scsiDev.phase = DATA_IN;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
cfgIdx += pageSize;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
// error.
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
}
|
||||
|
||||
void scsiInquiry()
|
||||
{
|
||||
uint8 evpd = scsiDev.cdb[1] & 1; // enable vital product data.
|
||||
uint8 pageCode = scsiDev.cdb[2];
|
||||
uint32 allocationLength = scsiDev.cdb[4];
|
||||
|
||||
// SASI standard, X3T9.3_185_RevE states that 0 == 256 bytes
|
||||
if (allocationLength == 0) allocationLength = 256;
|
||||
|
||||
if (!evpd)
|
||||
{
|
||||
if (pageCode)
|
||||
{
|
||||
// error.
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
else
|
||||
{
|
||||
const TargetConfig* config = scsiDev.target->cfg;
|
||||
memcpy(scsiDev.data, StandardResponse, sizeof(StandardResponse));
|
||||
scsiDev.data[1] = scsiDev.target->cfg->deviceTypeModifier;
|
||||
memcpy(&scsiDev.data[8], config->vendor, sizeof(config->vendor));
|
||||
memcpy(&scsiDev.data[16], config->prodId, sizeof(config->prodId));
|
||||
memcpy(&scsiDev.data[32], config->revision, sizeof(config->revision));
|
||||
scsiDev.dataLen = sizeof(StandardResponse) +
|
||||
sizeof(config->vendor) +
|
||||
sizeof(config->prodId) +
|
||||
sizeof(config->revision);
|
||||
scsiDev.phase = DATA_IN;
|
||||
}
|
||||
}
|
||||
else if (scsiDev.target->cfg->vpd[3] != 0)
|
||||
{
|
||||
useCustomVPD(scsiDev.target->cfg, pageCode);
|
||||
}
|
||||
else if (pageCode == 0x00)
|
||||
{
|
||||
memcpy(scsiDev.data, SupportedVitalPages, sizeof(SupportedVitalPages));
|
||||
scsiDev.dataLen = sizeof(SupportedVitalPages);
|
||||
scsiDev.phase = DATA_IN;
|
||||
}
|
||||
else if (pageCode == 0x80)
|
||||
{
|
||||
memcpy(scsiDev.data, UnitSerialNumber, sizeof(UnitSerialNumber));
|
||||
scsiDev.dataLen = sizeof(UnitSerialNumber);
|
||||
scsiDev.phase = DATA_IN;
|
||||
}
|
||||
else if (pageCode == 0x81)
|
||||
{
|
||||
memcpy(
|
||||
scsiDev.data,
|
||||
ImpOperatingDefinition,
|
||||
sizeof(ImpOperatingDefinition));
|
||||
scsiDev.dataLen = sizeof(ImpOperatingDefinition);
|
||||
scsiDev.phase = DATA_IN;
|
||||
}
|
||||
else if (pageCode == 0x82)
|
||||
{
|
||||
memcpy(
|
||||
scsiDev.data,
|
||||
AscImpOperatingDefinition,
|
||||
sizeof(AscImpOperatingDefinition));
|
||||
scsiDev.dataLen = sizeof(AscImpOperatingDefinition);
|
||||
scsiDev.phase = DATA_IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
// error.
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
|
||||
|
||||
if (scsiDev.phase == DATA_IN)
|
||||
{
|
||||
// "real" hard drives send back exactly allocationLenth bytes, padded
|
||||
// with zeroes. This only seems to happen for Inquiry responses, and not
|
||||
// other commands that also supply an allocation length such as Mode Sense or
|
||||
// Request Sense.
|
||||
// (See below for exception to this rule when 0 allocation length)
|
||||
if (scsiDev.dataLen < allocationLength)
|
||||
{
|
||||
memset(
|
||||
&scsiDev.data[scsiDev.dataLen],
|
||||
0,
|
||||
allocationLength - scsiDev.dataLen);
|
||||
}
|
||||
// Spec 8.2.5 requires us to simply truncate the response if it's
|
||||
// too big.
|
||||
scsiDev.dataLen = allocationLength;
|
||||
|
||||
// Set the device type as needed.
|
||||
switch (scsiDev.target->cfg->deviceType)
|
||||
{
|
||||
case CONFIG_OPTICAL:
|
||||
scsiDev.data[0] = 0x05; // device type
|
||||
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.
|
||||
break;
|
||||
default:
|
||||
// Accept defaults for a fixed disk.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the first byte to indicate LUN presence.
|
||||
if (scsiDev.lun) // We only support lun 0
|
||||
{
|
||||
scsiDev.data[0] = 0x7F;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
// Copyright (C) 2013 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 "inquiry.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static uint8 StandardResponse[] =
|
||||
{
|
||||
0x00, // "Direct-access device". AKA standard hard disk
|
||||
0x00, // device type modifier
|
||||
0x02, // Complies with ANSI SCSI-2.
|
||||
0x01, // Response format is compatible with the old CCS format.
|
||||
0x1f, // standard length.
|
||||
0, 0, // Reserved
|
||||
0x08 // Enable linked commands
|
||||
};
|
||||
// Vendor set by config 'c','o','d','e','s','r','c',' ',
|
||||
// prodId set by config'S','C','S','I','2','S','D',' ',' ',' ',' ',' ',' ',' ',' ',' ',
|
||||
// Revision set by config'2','.','0','a'
|
||||
|
||||
/* For reference, here's a dump from an Apple branded 500Mb drive from 1994.
|
||||
$ sudo sg_inq -H /dev/sdd --len 255
|
||||
standard INQUIRY:
|
||||
00 00 00 02 01 31 00 00 18 51 55 41 4e 54 55 4d 20 ....1...QUANTUM
|
||||
10 4c 50 53 32 37 30 20 20 20 20 20 20 20 20 20 20 LPS270
|
||||
20 30 39 30 30 00 00 00 d9 b0 27 34 01 04 b3 01 1b 0900.....'4.....
|
||||
30 07 00 a0 00 00 ff ......
|
||||
Vendor identification: QUANTUM
|
||||
Product identification: LPS270
|
||||
Product revision level: 0900
|
||||
*/
|
||||
|
||||
|
||||
static const uint8 SupportedVitalPages[] =
|
||||
{
|
||||
0x00, // "Direct-access device". AKA standard hard disk
|
||||
0x00, // Page Code
|
||||
0x00, // Reserved
|
||||
0x04, // Page length
|
||||
0x00, // Support "Supported vital product data pages"
|
||||
0x80, // Support "Unit serial number page"
|
||||
0x81, // Support "Implemented operating definition page"
|
||||
0x82 // Support "ASCII Implemented operating definition page"
|
||||
};
|
||||
|
||||
static const uint8 UnitSerialNumber[] =
|
||||
{
|
||||
0x00, // "Direct-access device". AKA standard hard disk
|
||||
0x80, // Page Code
|
||||
0x00, // Reserved
|
||||
0x10, // Page length
|
||||
'c','o','d','e','s','r','c','-','1','2','3','4','5','6','7','8'
|
||||
};
|
||||
|
||||
static const uint8 ImpOperatingDefinition[] =
|
||||
{
|
||||
0x00, // "Direct-access device". AKA standard hard disk
|
||||
0x81, // Page Code
|
||||
0x00, // Reserved
|
||||
0x03, // Page length
|
||||
0x03, // Current: SCSI-2 operating definition
|
||||
0x03, // Default: SCSI-2 operating definition
|
||||
0x03 // Supported (list): SCSI-2 operating definition.
|
||||
};
|
||||
|
||||
static const uint8 AscImpOperatingDefinition[] =
|
||||
{
|
||||
0x00, // "Direct-access device". AKA standard hard disk
|
||||
0x82, // Page Code
|
||||
0x00, // Reserved
|
||||
0x07, // Page length
|
||||
0x06, // Ascii length
|
||||
'S','C','S','I','-','2'
|
||||
};
|
||||
|
||||
static void useCustomVPD(const TargetConfig* cfg, int pageCode)
|
||||
{
|
||||
int cfgIdx = 0;
|
||||
int found = 0;
|
||||
while ((cfgIdx < sizeof(cfg->vpd) - 4) &&
|
||||
(cfg->vpd[cfgIdx + 3] != 0)
|
||||
)
|
||||
{
|
||||
int pageSize = cfg->vpd[cfgIdx + 3] + 4;
|
||||
int dataPageCode = cfg->vpd[cfgIdx + 1];
|
||||
if (dataPageCode == pageCode)
|
||||
{
|
||||
memcpy(scsiDev.data, &(cfg->vpd[cfgIdx]), pageSize);
|
||||
scsiDev.dataLen = pageSize;
|
||||
scsiDev.phase = DATA_IN;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
cfgIdx += pageSize;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
// error.
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
}
|
||||
|
||||
void scsiInquiry()
|
||||
{
|
||||
uint8 evpd = scsiDev.cdb[1] & 1; // enable vital product data.
|
||||
uint8 pageCode = scsiDev.cdb[2];
|
||||
uint32 allocationLength = scsiDev.cdb[4];
|
||||
|
||||
// SASI standard, X3T9.3_185_RevE states that 0 == 256 bytes
|
||||
// BUT SCSI 2 standard says 0 == 0.
|
||||
if (scsiDev.compatMode <= COMPAT_SCSI1) // excludes COMPAT_SCSI2_DISABLED
|
||||
{
|
||||
if (allocationLength == 0) allocationLength = 256;
|
||||
}
|
||||
|
||||
if (!evpd)
|
||||
{
|
||||
if (pageCode)
|
||||
{
|
||||
// error.
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
else
|
||||
{
|
||||
const TargetConfig* config = scsiDev.target->cfg;
|
||||
memcpy(scsiDev.data, StandardResponse, sizeof(StandardResponse));
|
||||
scsiDev.data[1] = scsiDev.target->cfg->deviceTypeModifier;
|
||||
|
||||
if (scsiDev.compatMode >= COMPAT_SCSI2)
|
||||
{
|
||||
scsiDev.data[3] = 2; // SCSI 2 response format.
|
||||
}
|
||||
memcpy(&scsiDev.data[8], config->vendor, sizeof(config->vendor));
|
||||
memcpy(&scsiDev.data[16], config->prodId, sizeof(config->prodId));
|
||||
memcpy(&scsiDev.data[32], config->revision, sizeof(config->revision));
|
||||
scsiDev.dataLen = sizeof(StandardResponse) +
|
||||
sizeof(config->vendor) +
|
||||
sizeof(config->prodId) +
|
||||
sizeof(config->revision);
|
||||
scsiDev.phase = DATA_IN;
|
||||
}
|
||||
}
|
||||
else if (scsiDev.target->cfg->vpd[3] != 0)
|
||||
{
|
||||
useCustomVPD(scsiDev.target->cfg, pageCode);
|
||||
}
|
||||
else if (pageCode == 0x00)
|
||||
{
|
||||
memcpy(scsiDev.data, SupportedVitalPages, sizeof(SupportedVitalPages));
|
||||
scsiDev.dataLen = sizeof(SupportedVitalPages);
|
||||
scsiDev.phase = DATA_IN;
|
||||
}
|
||||
else if (pageCode == 0x80)
|
||||
{
|
||||
memcpy(scsiDev.data, UnitSerialNumber, sizeof(UnitSerialNumber));
|
||||
scsiDev.dataLen = sizeof(UnitSerialNumber);
|
||||
scsiDev.phase = DATA_IN;
|
||||
}
|
||||
else if (pageCode == 0x81)
|
||||
{
|
||||
memcpy(
|
||||
scsiDev.data,
|
||||
ImpOperatingDefinition,
|
||||
sizeof(ImpOperatingDefinition));
|
||||
scsiDev.dataLen = sizeof(ImpOperatingDefinition);
|
||||
scsiDev.phase = DATA_IN;
|
||||
}
|
||||
else if (pageCode == 0x82)
|
||||
{
|
||||
memcpy(
|
||||
scsiDev.data,
|
||||
AscImpOperatingDefinition,
|
||||
sizeof(AscImpOperatingDefinition));
|
||||
scsiDev.dataLen = sizeof(AscImpOperatingDefinition);
|
||||
scsiDev.phase = DATA_IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
// error.
|
||||
scsiDev.status = CHECK_CONDITION;
|
||||
scsiDev.target->sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
|
||||
scsiDev.phase = STATUS;
|
||||
}
|
||||
|
||||
|
||||
if (scsiDev.phase == DATA_IN)
|
||||
{
|
||||
// "real" hard drives send back exactly allocationLenth bytes, padded
|
||||
// with zeroes. This only seems to happen for Inquiry responses, and not
|
||||
// other commands that also supply an allocation length such as Mode Sense or
|
||||
// Request Sense.
|
||||
// (See below for exception to this rule when 0 allocation length)
|
||||
if (scsiDev.dataLen < allocationLength)
|
||||
{
|
||||
memset(
|
||||
&scsiDev.data[scsiDev.dataLen],
|
||||
0,
|
||||
allocationLength - scsiDev.dataLen);
|
||||
}
|
||||
// Spec 8.2.5 requires us to simply truncate the response if it's
|
||||
// too big.
|
||||
scsiDev.dataLen = allocationLength;
|
||||
|
||||
// Set the device type as needed.
|
||||
switch (scsiDev.target->cfg->deviceType)
|
||||
{
|
||||
case CONFIG_OPTICAL:
|
||||
scsiDev.data[0] = 0x05; // device type
|
||||
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.
|
||||
break;
|
||||
default:
|
||||
// Accept defaults for a fixed disk.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the first byte to indicate LUN presence.
|
||||
if (scsiDev.lun) // We only support lun 0
|
||||
{
|
||||
scsiDev.data[0] = 0x7F;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "debug.h"
|
||||
#include "tape.h"
|
||||
#include "mo.h"
|
||||
#include "vendor.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -138,6 +139,16 @@ void process_Status()
|
||||
uint8 message;
|
||||
|
||||
uint8 control = scsiDev.cdb[scsiDev.cdbLen - 1];
|
||||
|
||||
if (scsiDev.target->cfg->quirks == CONFIG_QUIRKS_OMTI)
|
||||
{
|
||||
// OMTI non-standard LINK control
|
||||
if (control & 0x01)
|
||||
{
|
||||
scsiDev.phase = COMMAND; return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((scsiDev.status == GOOD) && (control & 0x01))
|
||||
{
|
||||
// Linked command.
|
||||
@ -155,6 +166,10 @@ void process_Status()
|
||||
{
|
||||
message = MSG_COMMAND_COMPLETE;
|
||||
}
|
||||
|
||||
// TODO OMTI ENABLE VIA CONFIG
|
||||
// scsiDev.status |= (scsiDev.target->targetId & 0x03) << 5 ;
|
||||
|
||||
scsiWriteByte(scsiDev.status);
|
||||
|
||||
scsiDev.lastStatus = scsiDev.status;
|
||||
@ -403,7 +418,7 @@ static void process_Command()
|
||||
{
|
||||
scsiReadBuffer();
|
||||
}
|
||||
else if (!scsiModeCommand())
|
||||
else if (!scsiModeCommand() && !scsiVendorCommand())
|
||||
{
|
||||
scsiDev.target->sense.code = ILLEGAL_REQUEST;
|
||||
scsiDev.target->sense.asc = INVALID_COMMAND_OPERATION_CODE;
|
||||
@ -566,7 +581,7 @@ static void process_SelectionPhase()
|
||||
|
||||
// Only read these pins AFTER SEL and BSY - we don't want to catch them
|
||||
// during a transition period.
|
||||
uint8 mask = scsiReadDBxPins();
|
||||
uint8 mask = (selLatchCfg && scsiDev.selFlag) ? scsiDev.selDBX : scsiReadDBxPins();
|
||||
int maskBitCount = countBits(mask);
|
||||
int goodParity = (Lookup_OddParity[mask] == SCSI_ReadPin(SCSI_In_DBP));
|
||||
int atnFlag = SCSI_ReadFilt(SCSI_Filt_ATN);
|
||||
@ -617,9 +632,9 @@ static void process_SelectionPhase()
|
||||
}
|
||||
else if (!(scsiDev.boardCfg.flags & CONFIG_ENABLE_SCSI2))
|
||||
{
|
||||
scsiDev.compatMode = COMPAT_SCSI1;
|
||||
scsiDev.compatMode = COMPAT_SCSI2_DISABLED;
|
||||
}
|
||||
else if (scsiDev.compatMode == COMPAT_UNKNOWN)
|
||||
else
|
||||
{
|
||||
scsiDev.compatMode = COMPAT_SCSI2;
|
||||
}
|
||||
|
@ -61,6 +61,11 @@ typedef enum
|
||||
{
|
||||
COMPAT_UNKNOWN,
|
||||
COMPAT_SCSI1,
|
||||
|
||||
// Messages are being used, yet SCSI 2 mode is disabled.
|
||||
// This impacts interpretation of INQUIRY commands.
|
||||
COMPAT_SCSI2_DISABLED,
|
||||
|
||||
COMPAT_SCSI2
|
||||
} SCSI_COMPAT_MODE;
|
||||
|
||||
@ -106,12 +111,14 @@ typedef struct
|
||||
|
||||
// Set to true (1) if the RST flag was set.
|
||||
volatile int resetFlag;
|
||||
|
||||
|
||||
// Set to true (1) if the SEL flag was set.
|
||||
volatile int selFlag;
|
||||
|
||||
|
||||
// Set to true (1) if a parity error was observed.
|
||||
int parityError;
|
||||
int parityError;
|
||||
|
||||
volatile int selDBX;
|
||||
|
||||
int phase;
|
||||
|
||||
|
@ -80,6 +80,9 @@ CY_ISR(scsiSelectionISR)
|
||||
// selFlag is required for Philips P2000C which releases it after 600ns
|
||||
// without waiting for BSY.
|
||||
scsiDev.selFlag = 1;
|
||||
|
||||
// Required for some early Mac Plus roms
|
||||
scsiDev.selDBX = scsiReadDBxPins();
|
||||
}
|
||||
|
||||
uint8_t
|
||||
|
Binary file not shown.
@ -144,6 +144,13 @@
|
||||
<build_action v="C_FILE" />
|
||||
<PropertyDeltas />
|
||||
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
|
||||
<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFile" version="3" xml_contents_version="1">
|
||||
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItem" version="2" name="vendor.c" persistent="..\..\src\vendor.c">
|
||||
<Hidden v="False" />
|
||||
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
|
||||
<build_action v="C_FILE" />
|
||||
<PropertyDeltas />
|
||||
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
|
||||
</dependencies>
|
||||
</CyGuid_0820c2e7-528d-4137-9a08-97257b946089>
|
||||
</CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8>
|
||||
@ -308,6 +315,13 @@
|
||||
<build_action v="NONE" />
|
||||
<PropertyDeltas />
|
||||
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
|
||||
<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFile" version="3" xml_contents_version="1">
|
||||
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItem" version="2" name="vendor.h" persistent="..\..\src\vendor.h">
|
||||
<Hidden v="False" />
|
||||
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
|
||||
<build_action v="NONE" />
|
||||
<PropertyDeltas />
|
||||
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
|
||||
</dependencies>
|
||||
</CyGuid_0820c2e7-528d-4137-9a08-97257b946089>
|
||||
</CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8>
|
||||
|
Binary file not shown.
@ -144,6 +144,13 @@
|
||||
<build_action v="C_FILE" />
|
||||
<PropertyDeltas />
|
||||
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
|
||||
<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFile" version="3" xml_contents_version="1">
|
||||
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItem" version="2" name="vendor.c" persistent="..\..\src\vendor.c">
|
||||
<Hidden v="False" />
|
||||
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
|
||||
<build_action v="C_FILE" />
|
||||
<PropertyDeltas />
|
||||
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
|
||||
</dependencies>
|
||||
</CyGuid_0820c2e7-528d-4137-9a08-97257b946089>
|
||||
</CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8>
|
||||
@ -308,6 +315,13 @@
|
||||
<build_action v="NONE" />
|
||||
<PropertyDeltas />
|
||||
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
|
||||
<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFile" version="3" xml_contents_version="1">
|
||||
<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItem" version="2" name="vendor.h" persistent="..\..\src\vendor.h">
|
||||
<Hidden v="False" />
|
||||
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
|
||||
<build_action v="NONE" />
|
||||
<PropertyDeltas />
|
||||
</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>
|
||||
</dependencies>
|
||||
</CyGuid_0820c2e7-528d-4137-9a08-97257b946089>
|
||||
</CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8>
|
||||
|
@ -46,8 +46,18 @@ extern "C" {
|
||||
|Row 188 | Config target 0
|
||||
---------------------------------
|
||||
|Row 187 | Board Config
|
||||
| ... | Empty
|
||||
|Row 172 | Empty
|
||||
---------------------------------
|
||||
|Row 186 |
|
||||
|Row 171 |
|
||||
| ... |
|
||||
|Row 156 | Config target 6
|
||||
| ... |
|
||||
|Row 140 | Config target 5
|
||||
| ... |
|
||||
|Row 124 | Config target 4
|
||||
---------------------------------
|
||||
|Row 123 |
|
||||
| ... |
|
||||
|Row 0 |
|
||||
--------| |
|
||||
@ -65,6 +75,7 @@ extern "C" {
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
//#define MAX_SCSI_TARGETS 7
|
||||
#define MAX_SCSI_TARGETS 4
|
||||
#define SCSI_CONFIG_ARRAY 1
|
||||
#define SCSI_CONFIG_ROWS 16
|
||||
@ -77,6 +88,9 @@ extern "C" {
|
||||
#define SCSI_CONFIG_1_ROW 204
|
||||
#define SCSI_CONFIG_2_ROW 220
|
||||
#define SCSI_CONFIG_3_ROW 236
|
||||
#define SCSI_CONFIG_4_ROW 124
|
||||
#define SCSI_CONFIG_5_ROW 140
|
||||
#define SCSI_CONFIG_6_ROW 156
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@ -110,7 +124,8 @@ typedef enum
|
||||
typedef enum
|
||||
{
|
||||
CONFIG_QUIRKS_NONE,
|
||||
CONFIG_QUIRKS_APPLE
|
||||
CONFIG_QUIRKS_APPLE,
|
||||
CONFIG_QUIRKS_OMTI
|
||||
} CONFIG_QUIRKS;
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
|
41
software/scsi2sd-util/ConfigUtil.cc
Normal file → Executable file
41
software/scsi2sd-util/ConfigUtil.cc
Normal file → Executable file
@ -248,9 +248,19 @@ ConfigUtil::toXML(const TargetConfig& config)
|
||||
" <!-- ********************************************************\n" <<
|
||||
" Space separated list. Available options:\n" <<
|
||||
" apple\t\tReturns Apple-specific mode pages\n" <<
|
||||
" omti\t\tOMTI host non-standard link control\n" <<
|
||||
" ********************************************************* -->\n" <<
|
||||
" <quirks>" <<
|
||||
(config.quirks & CONFIG_QUIRKS_APPLE ? "apple" : "") <<
|
||||
" <quirks>";
|
||||
if (config.quirks == CONFIG_QUIRKS_APPLE)
|
||||
{
|
||||
s << "apple";
|
||||
}
|
||||
else if (config.quirks == CONFIG_QUIRKS_OMTI)
|
||||
{
|
||||
s << "omti";
|
||||
}
|
||||
|
||||
s <<
|
||||
"</quirks>\n" <<
|
||||
|
||||
"\n\n" <<
|
||||
@ -393,6 +403,19 @@ ConfigUtil::toXML(const BoardConfig& config)
|
||||
" <mapLunsToIds>" <<
|
||||
(config.flags & CONFIG_MAP_LUNS_TO_IDS ? "true" : "false") <<
|
||||
"</mapLunsToIds>\n" <<
|
||||
|
||||
" <!-- ********************************************************\n" <<
|
||||
" Delay (in milliseconds) before responding to a SCSI selection.\n" <<
|
||||
" 255 (auto) sets it to 0 for SCSI2 hosts and 1ms otherwise.\n" <<
|
||||
" Some samplers need this set to 1 manually.\n" <<
|
||||
" ********************************************************* -->\n" <<
|
||||
" <selectionDelay>" << static_cast<int>(config.selectionDelay) << "</selectionDelay>\n" <<
|
||||
|
||||
" <!-- ********************************************************\n" <<
|
||||
" Startup delay (in seconds) before responding to the SCSI bus \n" <<
|
||||
" after power on. Default = 0.\n" <<
|
||||
" ********************************************************* -->\n" <<
|
||||
" <startupDelay>" << static_cast<int>(config.startupDelay) << "</startupDelay>\n" <<
|
||||
"</BoardConfig>\n";
|
||||
|
||||
return s.str();
|
||||
@ -471,6 +494,10 @@ parseTarget(wxXmlNode* node)
|
||||
{
|
||||
result.quirks |= CONFIG_QUIRKS_APPLE;
|
||||
}
|
||||
else if (quirk == "omti")
|
||||
{
|
||||
result.quirks |= CONFIG_QUIRKS_OMTI;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (child->GetName() == "deviceType")
|
||||
@ -559,7 +586,15 @@ parseBoardConfig(wxXmlNode* node)
|
||||
wxXmlNode *child = node->GetChildren();
|
||||
while (child)
|
||||
{
|
||||
if (child->GetName() == "unitAttention")
|
||||
if (child->GetName() == "selectionDelay")
|
||||
{
|
||||
result.selectionDelay = parseInt(child, 255);
|
||||
}
|
||||
else if (child->GetName() == "startupDelay")
|
||||
{
|
||||
result.startupDelay = parseInt(child, 255);
|
||||
}
|
||||
else if (child->GetName() == "unitAttention")
|
||||
{
|
||||
std::string s(child->GetNodeContent().mb_str());
|
||||
if (s == "true")
|
||||
|
@ -42,7 +42,8 @@ LDFLAGS += -L$(BUILD)/libzipper/.libs -lzipper $(LDFLAGS_ZLIB) $(LDFLAGS_HIDAPI)
|
||||
|
||||
# wxWidgets 3.0.2 uses broken Webkit headers under OSX Yosemeti
|
||||
# liblzma not available on OSX 10.7
|
||||
WX_CONFIG=--disable-webkit --disable-webviewwebkit \
|
||||
# --disable-mediactrl for missing Quicktime.h on Mac OSX Sierra
|
||||
WX_CONFIG=--disable-webkit --disable-webviewwebkit --disable-mediactrl \
|
||||
--without-libtiff --without-libjbig --without-liblzma --without-opengl \
|
||||
--enable-monolithic --enable-stl --disable-shared
|
||||
|
||||
@ -80,6 +81,13 @@ ifeq ($(TARGET),Darwin)
|
||||
CXX=clang++ -stdlib=libc++ -mmacosx-version-min=10.7
|
||||
WX_CONFIG += --with-macosx-version-min=10.7
|
||||
BUILD := $(PWD)/build/mac
|
||||
all: $(BUILD)/scsi2sd-util.dmg
|
||||
|
||||
$(BUILD)/scsi2sd-util.dmg: $(BUILD)/scsi2sd-util $(BUILD)/scsi2sd-monitor
|
||||
mkdir -p $(dir $@)/dmg
|
||||
cp $(BUILD)/scsi2sd-util $(BUILD)/scsi2sd-monitor $(dir $@)/dmg
|
||||
chmod a+rx $(dir $@)/dmg/*
|
||||
hdiutil create -srcfolder $(dir $@)/dmg $@
|
||||
endif
|
||||
|
||||
export CC CXX
|
||||
|
2
software/scsi2sd-util/TargetPanel.cc
Normal file → Executable file
2
software/scsi2sd-util/TargetPanel.cc
Normal file → Executable file
@ -312,7 +312,7 @@ TargetPanel::evaluate()
|
||||
{
|
||||
case CONFIG_OPTICAL:
|
||||
mySectorSizeCtrl->ChangeValue("2048");
|
||||
mySectorSizeCtrl->Enable(false);
|
||||
mySectorSizeCtrl->Enable(true); // Enable override
|
||||
break;
|
||||
case CONFIG_FLOPPY_14MB:
|
||||
mySectorSizeCtrl->ChangeValue("512");
|
||||
|
@ -570,7 +570,7 @@ private:
|
||||
std::vector<zipper::CompressedFilePtr> files(decomp.getEntries());
|
||||
for (auto it(files.begin()); it != files.end(); it++)
|
||||
{
|
||||
if (myBootloader->isCorrectFirmware((*it)->getPath()))
|
||||
if (myBootloader && myBootloader->isCorrectFirmware((*it)->getPath()))
|
||||
{
|
||||
std::stringstream msg;
|
||||
msg << "Found firmware entry " << (*it)->getPath() <<
|
||||
@ -1007,11 +1007,13 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
flashRow = SCSI_CONFIG_0_ROW;
|
||||
for (size_t i = 0;
|
||||
i < myTargets.size();
|
||||
++i, flashRow += SCSI_CONFIG_ROWS)
|
||||
++i)
|
||||
{
|
||||
flashRow = (i <= 3)
|
||||
? SCSI_CONFIG_0_ROW + (i*SCSI_CONFIG_ROWS)
|
||||
: SCSI_CONFIG_4_ROW + ((i-4)*SCSI_CONFIG_ROWS);
|
||||
std::vector<uint8_t> raw(sizeof(TargetConfig));
|
||||
|
||||
for (size_t j = 0; j < SCSI_CONFIG_ROWS; ++j)
|
||||
@ -1135,8 +1137,12 @@ private:
|
||||
flashRow = SCSI_CONFIG_0_ROW;
|
||||
for (size_t i = 0;
|
||||
i < myTargets.size();
|
||||
++i, flashRow += SCSI_CONFIG_ROWS)
|
||||
++i)
|
||||
{
|
||||
flashRow = (i <= 3)
|
||||
? SCSI_CONFIG_0_ROW + (i*SCSI_CONFIG_ROWS)
|
||||
: SCSI_CONFIG_4_ROW + ((i-4)*SCSI_CONFIG_ROWS);
|
||||
|
||||
TargetConfig config(myTargets[i]->getConfig());
|
||||
std::vector<uint8_t> raw(ConfigUtil::toBytes(config));
|
||||
|
||||
|
2
software/scsi2sd-util/wxWidgets/src/osx/carbon/dataobj.cpp
Normal file → Executable file
2
software/scsi2sd-util/wxWidgets/src/osx/carbon/dataobj.cpp
Normal file → Executable file
@ -30,7 +30,7 @@
|
||||
#include "wx/osx/private.h"
|
||||
|
||||
#if wxOSX_USE_COCOA_OR_CARBON
|
||||
#include <QuickTime/QuickTime.h>
|
||||
// #include <QuickTime/QuickTime.h>
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
2
software/scsi2sd-util/wxWidgets/src/osx/core/bitmap.cpp
Normal file → Executable file
2
software/scsi2sd-util/wxWidgets/src/osx/core/bitmap.cpp
Normal file → Executable file
@ -36,7 +36,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
|
||||
#endif
|
||||
|
||||
#ifndef __WXOSX_IPHONE__
|
||||
#include <QuickTime/QuickTime.h>
|
||||
//#include <QuickTime/QuickTime.h>
|
||||
#endif
|
||||
|
||||
CGColorSpaceRef wxMacGetGenericRGBColorSpace();
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
@ -5841,9 +5842,9 @@ void Editor::GoToLine(int lineNo) {
|
||||
}
|
||||
|
||||
static bool Close(Point pt1, Point pt2) {
|
||||
if (abs(pt1.x - pt2.x) > 3)
|
||||
if (std::abs(pt1.x - pt2.x) > 3)
|
||||
return false;
|
||||
if (abs(pt1.y - pt2.y) > 3)
|
||||
if (std::abs(pt1.y - pt2.y) > 3)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user