}\r
}\r
\r
+static int useCustomPages(TargetConfig* cfg, int pc, int pageCode, int* idx)\r
+{\r
+ int found = 0;\r
+ int cfgIdx = 0;\r
+ while ((cfgIdx < sizeof(cfg->modePages) + 2) &&\r
+ (cfg->modePages[cfgIdx + 1] != 0)\r
+ )\r
+ {\r
+ int pageSize = cfg->modePages[cfgIdx + 1] + 2;\r
+ int dataPageCode = cfg->modePages[cfgIdx] & 0x3f;\r
+ if ((dataPageCode == pageCode) ||\r
+ (pageCode == 0x3f)\r
+ )\r
+ {\r
+ pageIn(pc, *idx, &cfg->modePages[cfgIdx], pageSize);\r
+ *idx += pageSize;\r
+ found = 1;\r
+ if (pageCode != 0x3f)\r
+ {\r
+ break;\r
+ }\r
+ }\r
+ cfgIdx += pageSize;\r
+ }\r
+ return found;\r
+}\r
+\r
static void doModeSense(\r
int sixByteCmd, int dbd, int pc, int pageCode, int allocLength)\r
{\r
\r
int pageFound = 0;\r
\r
+ if (scsiDev.target->cfg->modePages[1] != 0)\r
+ {\r
+ pageFound = useCustomPages(scsiDev.target->cfg, pc, pageCode, &idx);\r
+ pageCode = 0xFF; // dodgy, skip rest of logic\r
+ }\r
+\r
if (pageCode == 0x01 || pageCode == 0x3F)\r
{\r
pageFound = 1;\r
#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>
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
ConfigUtil::toXML(const TargetConfig& config)
{
std::stringstream s;
+ std::vector<uint8_t> modePages(getModePages(config));
s <<
"<SCSITarget id=\"" <<
"\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();
" <!-- ********************************************************\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") <<
"</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") <<
" <!-- ********************************************************\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") <<
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();
}