Support custom mode pages

This commit is contained in:
Michael McMaster 2016-01-13 21:22:16 +10:00
parent 2be1bfb906
commit 760222798c
4 changed files with 85 additions and 11 deletions

View File

@ -1,3 +1,6 @@
2016xxxx 4.x
- Added support for configurable mode pages
20160111 4.6
- Fixed bug when using sector size that isn't a multiple of 4
(eg. 522 bytes)

View File

@ -197,6 +197,33 @@ static void pageIn(int pc, int dataIdx, const uint8* pageData, int pageLen)
}
}
static int useCustomPages(TargetConfig* cfg, int pc, int pageCode, int* idx)
{
int found = 0;
int cfgIdx = 0;
while ((cfgIdx < sizeof(cfg->modePages) + 2) &&
(cfg->modePages[cfgIdx + 1] != 0)
)
{
int pageSize = cfg->modePages[cfgIdx + 1] + 2;
int dataPageCode = cfg->modePages[cfgIdx] & 0x3f;
if ((dataPageCode == pageCode) ||
(pageCode == 0x3f)
)
{
pageIn(pc, *idx, &cfg->modePages[cfgIdx], pageSize);
*idx += pageSize;
found = 1;
if (pageCode != 0x3f)
{
break;
}
}
cfgIdx += pageSize;
}
return found;
}
static void doModeSense(
int sixByteCmd, int dbd, int pc, int pageCode, int allocLength)
{
@ -305,6 +332,12 @@ static void doModeSense(
int pageFound = 0;
if (scsiDev.target->cfg->modePages[1] != 0)
{
pageFound = useCustomPages(scsiDev.target->cfg, pc, pageCode, &idx);
pageCode = 0xFF; // dodgy, skip rest of logic
}
if (pageCode == 0x01 || pageCode == 0x3F)
{
pageFound = 1;

View File

@ -153,7 +153,8 @@ typedef struct __attribute__((packed))
uint8_t reserved[960]; // Pad out to 1024 bytes for main section.
uint8_t vpd[3072]; // Total size is 4k.
uint8_t modePages[1024];
uint8_t unused[2048]; // Total size is 4k.
} TargetConfig;
typedef struct __attribute__((packed))

View File

@ -23,6 +23,12 @@
#include <string.h>
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/base64.h>
#include <wx/buffer.h>
#include <wx/xml/xml.h>
@ -80,6 +86,22 @@ namespace
return toLE32(in);
}
std::vector<uint8_t> getModePages(const TargetConfig& cfg)
{
std::vector<uint8_t> result;
int i = 0;
while (i < sizeof(cfg.modePages) + 2)
{
int pageLen = cfg.modePages[i+1];
if (pageLen == 0) break;
std::copy(
&cfg.modePages[i],
&cfg.modePages[i+pageLen+2],
std::back_inserter(result));
i += pageLen + 2;
}
return result;
}
}
BoardConfig
@ -194,6 +216,7 @@ std::string
ConfigUtil::toXML(const TargetConfig& config)
{
std::stringstream s;
std::vector<uint8_t> modePages(getModePages(config));
s <<
"<SCSITarget id=\"" <<
@ -269,6 +292,13 @@ ConfigUtil::toXML(const TargetConfig& config)
"\n" <<
" <!-- 16 character serial number -->\n" <<
" <serial>" << std::string(config.serial, 16) << "</serial>\n" <<
"\n" <<
" <!-- Custom mode pages, base64 encoded, up to 1024 bytes.-->\n" <<
" <modePages>\n" <<
(modePages.size() == 0 ? "" :
wxBase64Encode(&modePages[0], modePages.size())) <<
"\n" <<
" </modePages>\n" <<
"</SCSITarget>\n";
return s.str();
@ -292,7 +322,7 @@ ConfigUtil::toXML(const BoardConfig& config)
" <!-- ********************************************************\n" <<
" Only set to true when using with a fast SCSI2 host\n " <<
" controller. This can cause problems with older/slower\n" <<
" hardware.\n" <<
" hardware.\n" <<
" ********************************************************* -->\n" <<
" <enableScsi2>" <<
(config.flags & CONFIG_ENABLE_SCSI2 ? "true" : "false") <<
@ -318,9 +348,9 @@ ConfigUtil::toXML(const BoardConfig& config)
"</enableDisconnect>\n" <<
" <!-- ********************************************************\n" <<
" Respond to very short duration selection attempts. This supports\n" <<
" non-standard hardware, but is generally safe to enable.\n" <<
" Required for Philips P2000C.\n" <<
" Respond to very short duration selection attempts. This supports\n" <<
" non-standard hardware, but is generally safe to enable.\n" <<
" Required for Philips P2000C.\n" <<
" ********************************************************* -->\n" <<
" <selLatch>" <<
(config.flags & CONFIG_ENABLE_SEL_LATCH? "true" : "false") <<
@ -328,12 +358,12 @@ ConfigUtil::toXML(const BoardConfig& config)
" <!-- ********************************************************\n" <<
" Convert luns to IDs. The unit must already be configured to respond\n" <<
" on the ID. Allows dual drives to be accessed from a \n" <<
" XEBEC S1410 SASI bridge.\n" <<
" eg. Configured for dual drives as IDs 0 and 1, but the XEBEC will\n" <<
" access the second disk as ID0, lun 1.\n" <<
" See ttp://bitsavers.trailing-edge.com/pdf/xebec/104524C_S1410Man_Aug83.pdf\n" <<
" Convert luns to IDs. The unit must already be configured to respond\n" <<
" on the ID. Allows dual drives to be accessed from a \n" <<
" XEBEC S1410 SASI bridge.\n" <<
" eg. Configured for dual drives as IDs 0 and 1, but the XEBEC will\n" <<
" access the second disk as ID0, lun 1.\n" <<
" See ttp://bitsavers.trailing-edge.com/pdf/xebec/104524C_S1410Man_Aug83.pdf\n" <<
" ********************************************************* -->\n" <<
" <mapLunsToIds>" <<
(config.flags & CONFIG_MAP_LUNS_TO_IDS ? "true" : "false") <<
@ -474,6 +504,13 @@ parseTarget(wxXmlNode* node)
memset(result.serial, ' ', sizeof(result.serial));
memcpy(result.serial, s.c_str(), s.size());
}
else if (child->GetName() == "modePages")
{
wxMemoryBuffer buf =
wxBase64Decode(child->GetNodeContent(), wxBase64DecodeMode_SkipWS);
size_t len = std::min(buf.GetDataLen(), sizeof(result.modePages));
memcpy(result.modePages, buf.GetData(), len);
}
child = child->GetNext();
}