Line 1... |
Line 1... |
// $Id: Rw11CntlRK11.cpp 628 2015-01-04 16:22:09Z mueller $
|
// $Id: Rw11CntlRK11.cpp 647 2015-02-17 22:35:36Z mueller $
|
//
|
//
|
// Copyright 2013-2015 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
// Copyright 2013-2015 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
// Other credits:
|
// Other credits:
|
// the boot code is from the simh project and Copyright Robert M Supnik
|
// the boot code is from the simh project and Copyright Robert M Supnik
|
//
|
//
|
Line 13... |
Line 13... |
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// for complete details.
|
// for complete details.
|
//
|
//
|
// Revision History:
|
// Revision History:
|
// Date Rev Version Comment
|
// Date Rev Version Comment
|
|
// 2015-02-17 647 2.0.1 use Nwrd2Nblk(); BUGFIX: revise RdmaPostExecCB()
|
// 2015-01-04 628 2.0 use Rw11RdmaDisk
|
// 2015-01-04 628 2.0 use Rw11RdmaDisk
|
// 2014-12-30 625 1.2 adopt to Rlink V4 attn logic
|
// 2014-12-30 625 1.2 adopt to Rlink V4 attn logic
|
// 2014-12-25 621 1.1 adopt to 4k word ibus window
|
// 2014-12-25 621 1.1 adopt to 4k word ibus window
|
// 2014-06-14 562 1.0.1 Add stats
|
// 2014-06-14 562 1.0.1 Add stats
|
// 2013-04-20 508 1.0 Initial version
|
// 2013-04-20 508 1.0 Initial version
|
// 2013-02-10 485 0.1 First draft
|
// 2013-02-10 485 0.1 First draft
|
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
|
|
/*!
|
/*!
|
\file
|
\file
|
\version $Id: Rw11CntlRK11.cpp 628 2015-01-04 16:22:09Z mueller $
|
\version $Id: Rw11CntlRK11.cpp 647 2015-02-17 22:35:36Z mueller $
|
\brief Implemenation of Rw11CntlRK11.
|
\brief Implemenation of Rw11CntlRK11.
|
*/
|
*/
|
|
|
#include "boost/bind.hpp"
|
#include "boost/bind.hpp"
|
#include "boost/foreach.hpp"
|
#include "boost/foreach.hpp"
|
Line 100... |
Line 101... |
const uint16_t Rw11CntlRK11::kRKCS_M_MEX;
|
const uint16_t Rw11CntlRK11::kRKCS_M_MEX;
|
const uint16_t Rw11CntlRK11::kRKCS_V_MEX;
|
const uint16_t Rw11CntlRK11::kRKCS_V_MEX;
|
const uint16_t Rw11CntlRK11::kRKCS_B_MEX;
|
const uint16_t Rw11CntlRK11::kRKCS_B_MEX;
|
const uint16_t Rw11CntlRK11::kRKCS_V_FUNC;
|
const uint16_t Rw11CntlRK11::kRKCS_V_FUNC;
|
const uint16_t Rw11CntlRK11::kRKCS_B_FUNC;
|
const uint16_t Rw11CntlRK11::kRKCS_B_FUNC;
|
const uint16_t Rw11CntlRK11::kRKCS_CRESET;
|
|
const uint16_t Rw11CntlRK11::kRKCS_WRITE;
|
|
const uint16_t Rw11CntlRK11::kRKCS_READ;
|
|
const uint16_t Rw11CntlRK11::kRKCS_WCHK;
|
|
const uint16_t Rw11CntlRK11::kRKCS_SEEK;
|
|
const uint16_t Rw11CntlRK11::kRKCS_RCHK;
|
|
const uint16_t Rw11CntlRK11::kRKCS_DRESET;
|
|
const uint16_t Rw11CntlRK11::kRKCS_WLOCK;
|
|
const uint16_t Rw11CntlRK11::kRKCS_M_GO;
|
const uint16_t Rw11CntlRK11::kRKCS_M_GO;
|
|
|
|
const uint16_t Rw11CntlRK11::kFUNC_CRESET;
|
|
const uint16_t Rw11CntlRK11::kFUNC_WRITE;
|
|
const uint16_t Rw11CntlRK11::kFUNC_READ;
|
|
const uint16_t Rw11CntlRK11::kFUNC_WCHK;
|
|
const uint16_t Rw11CntlRK11::kFUNC_SEEK;
|
|
const uint16_t Rw11CntlRK11::kFUNC_RCHK;
|
|
const uint16_t Rw11CntlRK11::kFUNC_DRESET;
|
|
const uint16_t Rw11CntlRK11::kFUNC_WLOCK;
|
|
|
const uint16_t Rw11CntlRK11::kRKDA_M_DRSEL;
|
const uint16_t Rw11CntlRK11::kRKDA_M_DRSEL;
|
const uint16_t Rw11CntlRK11::kRKDA_V_DRSEL;
|
const uint16_t Rw11CntlRK11::kRKDA_V_DRSEL;
|
const uint16_t Rw11CntlRK11::kRKDA_B_DRSEL;
|
const uint16_t Rw11CntlRK11::kRKDA_B_DRSEL;
|
const uint16_t Rw11CntlRK11::kRKDA_M_CYL;
|
const uint16_t Rw11CntlRK11::kRKDA_M_CYL;
|
const uint16_t Rw11CntlRK11::kRKDA_V_CYL;
|
const uint16_t Rw11CntlRK11::kRKDA_V_CYL;
|
Line 146... |
Line 148... |
fRd_lba(0),
|
fRd_lba(0),
|
fRd_nwrd(0),
|
fRd_nwrd(0),
|
fRd_fu(0),
|
fRd_fu(0),
|
fRd_ovr(false),
|
fRd_ovr(false),
|
fRdma(this,
|
fRdma(this,
|
boost::bind(&Rw11CntlRK11::RdmaPreExecCB, this, _1, _2, _3),
|
boost::bind(&Rw11CntlRK11::RdmaPreExecCB, this, _1, _2, _3, _4),
|
boost::bind(&Rw11CntlRK11::RdmaPostExecCB, this, _1, _2, _3, _4))
|
boost::bind(&Rw11CntlRK11::RdmaPostExecCB, this, _1, _2, _3, _4))
|
{
|
{
|
// must be here because Units have a back-ptr (not available at Rw11CntlBase)
|
// must be here because Units have a back-ptr (not available at Rw11CntlBase)
|
for (size_t i=0; i<NUnit(); i++) {
|
for (size_t i=0; i<NUnit(); i++) {
|
fspUnit[i].reset(new Rw11UnitRK11(this, i));
|
fspUnit[i].reset(new Rw11UnitRK11(this, i));
|
Line 347... |
Line 349... |
Rw11UnitRK11& unit = *fspUnit[dr];
|
Rw11UnitRK11& unit = *fspUnit[dr];
|
Rw11Cpu& cpu = Cpu();
|
Rw11Cpu& cpu = Cpu();
|
RlinkCommandList clist;
|
RlinkCommandList clist;
|
|
|
uint32_t lba = unit.Chs2Lba(cy,hd,se);
|
uint32_t lba = unit.Chs2Lba(cy,hd,se);
|
uint32_t nblk = (2*nwrd+unit.BlockSize()-1)/unit.BlockSize();
|
uint32_t nblk = unit.Nwrd2Nblk(nwrd);
|
|
|
uint16_t rker = 0;
|
uint16_t rker = 0;
|
uint16_t rkds = unit.Rkds();
|
uint16_t rkds = unit.Rkds();
|
|
|
if (fTraceLevel>0) {
|
if (fTraceLevel>0) {
|
Line 369... |
Line 371... |
<< " lba,nw=" << RosPrintf(lba,"d",4)
|
<< " lba,nw=" << RosPrintf(lba,"d",4)
|
<< "," << RosPrintf(nwrd,"d",5);
|
<< "," << RosPrintf(nwrd,"d",5);
|
}
|
}
|
|
|
// check for general abort conditions
|
// check for general abort conditions
|
if (fu != kRKCS_CRESET && // function not control reset
|
if (fu != kFUNC_CRESET && // function not control reset
|
(!unit.Virt())) { // and drive not attached
|
(!unit.Virt())) { // and drive not attached
|
rker = kRKER_M_NXD; // --> abort with NXD error
|
rker = kRKER_M_NXD; // --> abort with NXD error
|
|
|
} else if (fu != kRKCS_WRITE && // function neither write
|
} else if (fu != kFUNC_WRITE && // function neither write
|
fu != kRKCS_READ && // nor read
|
fu != kFUNC_READ && // nor read
|
(rkcs & (kRKCS_M_FMT|kRKCS_M_RWA))) { // and FMT or RWA set
|
(rkcs & (kRKCS_M_FMT|kRKCS_M_RWA))) { // and FMT or RWA set
|
rker = kRKER_M_PGE; // --> abort with PGE error
|
rker = kRKER_M_PGE; // --> abort with PGE error
|
} else if (rkcs & kRKCS_M_RWA) { // RWA not supported
|
} else if (rkcs & kRKCS_M_RWA) { // RWA not supported
|
rker = kRKER_M_DRE; // --> abort with DRE error
|
rker = kRKER_M_DRE; // --> abort with DRE error
|
}
|
}
|
|
|
if (rker) {
|
if (rker) {
|
cpu.AddWibr(clist, fBase+kRKER, rker);
|
cpu.AddWibr(clist, fBase+kRKER, rker);
|
if (fu == kRKCS_SEEK || fu == kRKCS_DRESET)
|
if (fu == kFUNC_SEEK || fu == kFUNC_DRESET)
|
cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_SBCLR | (1u<<dr));
|
cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_SBCLR | (1u<<dr));
|
cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
|
cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
|
LogRker(rker);
|
LogRker(rker);
|
Server().Exec(clist);
|
Server().Exec(clist);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
// check for overrun (read/write beyond cylinder 203
|
// check for overrun (read/write beyond cylinder 203)
|
// if found, truncate request length
|
// if found, truncate request length
|
bool ovr = lba + nblk > unit.NBlock();
|
bool ovr = lba + nblk > unit.NBlock();
|
if (ovr) nwrd = (unit.NBlock()-lba) * (unit.BlockSize()/2);
|
if (ovr) nwrd = (unit.NBlock()-lba) * (unit.BlockSize()/2);
|
|
|
// remember request parameters for call back
|
// remember request parameters for call back
|
Line 406... |
Line 408... |
fRd_nwrd = nwrd;
|
fRd_nwrd = nwrd;
|
fRd_ovr = ovr;
|
fRd_ovr = ovr;
|
fRd_fu = fu;
|
fRd_fu = fu;
|
|
|
// now handle the functions
|
// now handle the functions
|
if (fu == kRKCS_CRESET) { // Control reset -----------------
|
if (fu == kFUNC_CRESET) { // Control reset -----------------
|
fStats.Inc(kStatNFuncCreset);
|
fStats.Inc(kStatNFuncCreset);
|
cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_CRESET);
|
cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_CRESET);
|
|
|
} else if (fu == kRKCS_WRITE) { // Write -------------------------
|
} else if (fu == kFUNC_WRITE) { // Write -------------------------
|
// Note: WRITE+FMT is just WRITE
|
// Note: WRITE+FMT is just WRITE
|
fStats.Inc(kStatNFuncWrite);
|
fStats.Inc(kStatNFuncWrite);
|
if (se >= unit.NSector()) rker |= kRKER_M_NXS;
|
if (se >= unit.NSector()) rker |= kRKER_M_NXS;
|
if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
|
if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
|
if (unit.WProt()) rker |= kRKER_M_WLO;
|
if (unit.WProt()) rker |= kRKER_M_WLO;
|
Line 425... |
Line 427... |
fRdma.QueueDiskWrite(addr, nwrd,
|
fRdma.QueueDiskWrite(addr, nwrd,
|
Rw11Cpu::kCp_ah_m_22bit|Rw11Cpu::kCp_ah_m_ubmap,
|
Rw11Cpu::kCp_ah_m_22bit|Rw11Cpu::kCp_ah_m_ubmap,
|
lba, &unit);
|
lba, &unit);
|
}
|
}
|
|
|
} else if (fu == kRKCS_READ) { // Read --------------------------
|
} else if (fu == kFUNC_READ) { // Read --------------------------
|
fStats.Inc(kStatNFuncRead);
|
fStats.Inc(kStatNFuncRead);
|
if (se >= unit.NSector()) rker |= kRKER_M_NXS;
|
if (se >= unit.NSector()) rker |= kRKER_M_NXS;
|
if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
|
if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
|
if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE; // IBA not supported
|
if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE; // IBA not supported
|
if (rker) {
|
if (rker) {
|
Line 438... |
Line 440... |
fRdma.QueueDiskRead(addr, nwrd,
|
fRdma.QueueDiskRead(addr, nwrd,
|
Rw11Cpu::kCp_ah_m_22bit|Rw11Cpu::kCp_ah_m_ubmap,
|
Rw11Cpu::kCp_ah_m_22bit|Rw11Cpu::kCp_ah_m_ubmap,
|
lba, &unit);
|
lba, &unit);
|
}
|
}
|
|
|
} else if (fu == kRKCS_WCHK) { // Write Check -------------------
|
} else if (fu == kFUNC_WCHK) { // Write Check -------------------
|
fStats.Inc(kStatNFuncWchk);
|
fStats.Inc(kStatNFuncWchk);
|
if (se >= unit.NSector()) rker |= kRKER_M_NXS;
|
if (se >= unit.NSector()) rker |= kRKER_M_NXS;
|
if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
|
if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
|
if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE; // IBA not supported
|
if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE; // IBA not supported
|
if (rker) {
|
if (rker) {
|
Line 451... |
Line 453... |
fRdma.QueueDiskWriteCheck(addr, nwrd,
|
fRdma.QueueDiskWriteCheck(addr, nwrd,
|
Rw11Cpu::kCp_ah_m_22bit|Rw11Cpu::kCp_ah_m_ubmap,
|
Rw11Cpu::kCp_ah_m_22bit|Rw11Cpu::kCp_ah_m_ubmap,
|
lba, &unit);
|
lba, &unit);
|
}
|
}
|
|
|
} else if (fu == kRKCS_SEEK) { // Seek --------------------------
|
} else if (fu == kFUNC_SEEK) { // Seek --------------------------
|
fStats.Inc(kStatNFuncSeek);
|
fStats.Inc(kStatNFuncSeek);
|
if (se >= unit.NSector()) rker |= kRKER_M_NXS;
|
if (se >= unit.NSector()) rker |= kRKER_M_NXS;
|
if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
|
if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
|
if (rker) {
|
if (rker) {
|
cpu.AddWibr(clist, fBase+kRKER, rker);
|
cpu.AddWibr(clist, fBase+kRKER, rker);
|
Line 469... |
Line 471... |
unit.SetRkds(rkds);
|
unit.SetRkds(rkds);
|
cpu.AddWibr(clist, fBase+kRKDS, rkds);
|
cpu.AddWibr(clist, fBase+kRKDS, rkds);
|
cpu.AddWibr(clist, fBase+kRKMR, 1u<<dr); // issue seek done
|
cpu.AddWibr(clist, fBase+kRKMR, 1u<<dr); // issue seek done
|
}
|
}
|
|
|
} else if (fu == kRKCS_RCHK) { // Read Check --------------------
|
} else if (fu == kFUNC_RCHK) { // Read Check --------------------
|
fStats.Inc(kStatNFuncRchk);
|
fStats.Inc(kStatNFuncRchk);
|
if (se >= unit.NSector()) rker |= kRKER_M_NXS;
|
if (se >= unit.NSector()) rker |= kRKER_M_NXS;
|
if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
|
if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
|
if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE; // IBA not supported
|
if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE; // IBA not supported
|
if (rker) {
|
if (rker) {
|
AddErrorExit(clist, rker);
|
AddErrorExit(clist, rker);
|
} else {
|
} else {
|
AddNormalExit(clist, nwrd, 0); // no action, virt disks don't err
|
AddNormalExit(clist, nwrd, 0); // no action, virt disks don't err
|
}
|
}
|
|
|
} else if (fu == kRKCS_DRESET) { // Drive Reset -------------------
|
} else if (fu == kFUNC_DRESET) { // Drive Reset -------------------
|
fStats.Inc(kStatNFuncDreset);
|
fStats.Inc(kStatNFuncDreset);
|
cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
|
cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
|
cpu.AddWibr(clist, fBase+kRKMR, 1u<<dr); // issue seek done
|
cpu.AddWibr(clist, fBase+kRKMR, 1u<<dr); // issue seek done
|
|
|
} else if (fu == kRKCS_WLOCK) { // Write Lock --------------------
|
} else if (fu == kFUNC_WLOCK) { // Write Lock --------------------
|
fStats.Inc(kStatNFuncWlock);
|
fStats.Inc(kStatNFuncWlock);
|
rkds |= kRKDS_M_WPS; // set RKDS write protect flag
|
rkds |= kRKDS_M_WPS; // set RKDS write protect flag
|
unit.SetRkds(rkds);
|
unit.SetRkds(rkds);
|
unit.SetWProt(true);
|
unit.SetWProt(true);
|
cpu.AddWibr(clist, fBase+kRKDS, rkds);
|
cpu.AddWibr(clist, fBase+kRKDS, rkds);
|
Line 503... |
Line 505... |
}
|
}
|
|
|
//------------------------------------------+-----------------------------------
|
//------------------------------------------+-----------------------------------
|
//! FIXME_docs
|
//! FIXME_docs
|
|
|
void Rw11CntlRK11::RdmaPreExecCB(int stat, size_t nword,
|
void Rw11CntlRK11::RdmaPreExecCB(int stat, size_t nwdone, size_t nwnext,
|
RlinkCommandList& clist)
|
RlinkCommandList& clist)
|
{
|
{
|
// if last chunk and not doing WCHK add a labo and normal exit csr update
|
// if last chunk and not doing WCHK add a labo and normal exit csr update
|
if (stat == Rw11Rdma::kStatusBusyLast && fRd_fu != kRKCS_WCHK) {
|
if (stat == Rw11Rdma::kStatusBusyLast && fRd_fu != kFUNC_WCHK) {
|
clist.AddLabo();
|
clist.AddLabo();
|
AddNormalExit(clist, nword, 0);
|
AddNormalExit(clist, nwdone+nwnext, 0);
|
}
|
}
|
return;
|
return;
|
}
|
}
|
|
|
//------------------------------------------+-----------------------------------
|
//------------------------------------------+-----------------------------------
|
Line 525... |
Line 527... |
if (stat == Rw11Rdma::kStatusBusy) return;
|
if (stat == Rw11Rdma::kStatusBusy) return;
|
|
|
uint16_t rker = 0;
|
uint16_t rker = 0;
|
|
|
// handle write check
|
// handle write check
|
if (fRd_fu == kRKCS_WCHK) {
|
if (fRd_fu == kFUNC_WCHK) {
|
size_t nwcok = fRdma.WriteCheck(ndone);
|
size_t nwcok = fRdma.WriteCheck(ndone);
|
if (nwcok != ndone) { // if mismatch found
|
if (nwcok != ndone) { // if mismatch found
|
rker |= kRKER_M_WCE; // set error flag
|
rker |= kRKER_M_WCE; // set error flag
|
if (fRd_rkcs & kRKCS_M_SSE) { // if 'stop-on-soft' requested
|
if (fRd_rkcs & kRKCS_M_SSE) { // if 'stop-on-soft' requested
|
ndone = nwcok; // truncate word count
|
ndone = nwcok; // truncate word count
|
Line 586... |
Line 588... |
uint16_t rker)
|
uint16_t rker)
|
{
|
{
|
Rw11Cpu& cpu = Cpu();
|
Rw11Cpu& cpu = Cpu();
|
uint16_t dr = (fRd_rkda>>kRKDA_V_DRSEL) & kRKDA_B_DRSEL;
|
uint16_t dr = (fRd_rkda>>kRKDA_V_DRSEL) & kRKDA_B_DRSEL;
|
Rw11UnitRK11& unit = *fspUnit[dr];
|
Rw11UnitRK11& unit = *fspUnit[dr];
|
size_t bszwrd = unit.BlockSize()/2; // block size in words
|
|
|
|
size_t nblk = (ndone+bszwrd-1)/bszwrd;
|
size_t nblk = unit.Nwrd2Nblk(ndone);
|
|
|
uint32_t addr = fRd_addr + 2*ndone;
|
uint32_t addr = fRd_addr + 2*ndone;
|
size_t lba = fRd_lba + nblk;
|
size_t lba = fRd_lba + nblk;
|
uint32_t nrest = fRd_nwrd - ndone;
|
uint32_t nrest = fRd_nwrd - ndone;
|
|
|