Line 1... |
Line 1... |
// $Id: Rw11CntlRK11.cpp 515 2013-05-04 17:28:59Z mueller $
|
// $Id: Rw11CntlRK11.cpp 562 2014-06-15 17:23:18Z mueller $
|
//
|
//
|
// Copyright 2013- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
// Copyright 2013-2014 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
// Other credits:
|
// Other credits:
|
// the boot code from the simh project and Copyright Robert M Supnik
|
// the boot code is from the simh project and Copyright Robert M Supnik
|
//
|
//
|
// This program is free software; you may redistribute and/or modify it under
|
// This program is free software; you may redistribute and/or modify it under
|
// the terms of the GNU General Public License as published by the Free
|
// the terms of the GNU General Public License as published by the Free
|
// Software Foundation, either version 2, or at your option any later version.
|
// Software Foundation, either version 2, or at your option any later version.
|
//
|
//
|
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
|
|
// 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 515 2013-05-04 17:28:59Z mueller $
|
\version $Id: Rw11CntlRK11.cpp 562 2014-06-15 17:23:18Z 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 146... |
Line 147... |
{
|
{
|
// must here because Unit have a back-pointer (not available at Rw11CntlBase)
|
// must here because Unit have a back-pointer (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));
|
}
|
}
|
|
|
|
fStats.Define(kStatNFuncCreset , "NFuncCreset" , "func CRESET");
|
|
fStats.Define(kStatNFuncWrite , "NFuncWrite" , "func WRITE");
|
|
fStats.Define(kStatNFuncRead , "NFuncRead" , "func READ");
|
|
fStats.Define(kStatNFuncWchk , "NFuncWchk" , "func WCHK");
|
|
fStats.Define(kStatNFuncSeek , "NFuncSeek" , "func SEEK");
|
|
fStats.Define(kStatNFuncRchk , "NFuncRchk" , "func RCHK");
|
|
fStats.Define(kStatNFuncDreset , "NFuncDreset" , "func DRESET");
|
|
fStats.Define(kStatNFuncWlock , "NFuncWlock " , "func WLOCK");
|
|
fStats.Define(kStatNRdmaWrite , "NRdmaWrite" , "rdma WRITE");
|
|
fStats.Define(kStatNRdmaRead , "NRdmaRead" , "rdma READ");
|
|
fStats.Define(kStatNRdmaWchk , "NRdmaWchk" , "rdma WCHK");
|
|
fStats.Define(kStatNRdmaRchk , "NRdmaRchk" , "rdma RCHK");
|
}
|
}
|
|
|
//------------------------------------------+-----------------------------------
|
//------------------------------------------+-----------------------------------
|
//! Destructor
|
//! Destructor
|
|
|
Line 169... |
Line 183... |
//! FIXME_docs
|
//! FIXME_docs
|
|
|
void Rw11CntlRK11::Start()
|
void Rw11CntlRK11::Start()
|
{
|
{
|
if (fStarted || fLam<0 || !fEnable || !fProbe.Found())
|
if (fStarted || fLam<0 || !fEnable || !fProbe.Found())
|
throw Rexception("Rw11CntlDL11::Start",
|
throw Rexception("Rw11CntlRK11::Start",
|
"Bad state: started, no lam, not enable, not found");
|
"Bad state: started, no lam, not enable, not found");
|
|
|
// setup primary info clist
|
// setup primary info clist
|
fPrimClist.Clear();
|
fPrimClist.Clear();
|
Cpu().AddIbrb(fPrimClist, fBase);
|
Cpu().AddIbrb(fPrimClist, fBase);
|
Line 222... |
Line 236... |
|
|
bool Rw11CntlRK11::BootCode(size_t unit, std::vector<uint16_t>& code,
|
bool Rw11CntlRK11::BootCode(size_t unit, std::vector<uint16_t>& code,
|
uint16_t& aload, uint16_t& astart)
|
uint16_t& aload, uint16_t& astart)
|
{
|
{
|
uint16_t kBOOT_START = 02000;
|
uint16_t kBOOT_START = 02000;
|
uint16_t bootcode[] = { // rk05 boot loader - from simh pdp11_rk.c
|
uint16_t bootcode[] = { // rk11 boot loader - from simh pdp11_rk.c (v3.9)
|
0042113, // "KD"
|
0042113, // "KD"
|
0012706, kBOOT_START, // MOV #boot_start, SP
|
0012706, kBOOT_START, // MOV #boot_start, SP
|
0012700, uint16_t(unit), // MOV #unit, R0 ; unit number
|
0012700, uint16_t(unit), // MOV #unit, R0 ; unit number
|
0010003, // MOV R0, R3
|
0010003, // MOV R0, R3
|
0000303, // SWAB R3
|
0000303, // SWAB R3
|
Line 240... |
Line 254... |
0005041, // CLR -(R1) ; clear ba
|
0005041, // CLR -(R1) ; clear ba
|
0012741, 0177000, // MOV #-256.*2, -(R1) ; load wc
|
0012741, 0177000, // MOV #-256.*2, -(R1) ; load wc
|
0012741, 0000005, // MOV #READ+GO, -(R1) ; read & go
|
0012741, 0000005, // MOV #READ+GO, -(R1) ; read & go
|
0005002, // CLR R2
|
0005002, // CLR R2
|
0005003, // CLR R3
|
0005003, // CLR R3
|
0012704, uint16_t(kBOOT_START+020), // MOV #START+20, R4
|
0012704, uint16_t(kBOOT_START+020), // MOV #START+20, R4 ; ?? unclear ??
|
0005005, // CLR R5
|
0005005, // CLR R5
|
0105711, // TSTB (R1)
|
0105711, // TSTB (R1)
|
0100376, // BPL .-4
|
0100376, // BPL .-4
|
0105011, // CLRB (R1)
|
0105011, // CLRB (R1)
|
0005007 // CLR PC (5007)
|
0005007 // CLR PC (5007)
|
Line 374... |
Line 388... |
if (ovr) nwrd = (unit.NBlock()-lba) * (unit.BlockSize()/2);
|
if (ovr) nwrd = (unit.NBlock()-lba) * (unit.BlockSize()/2);
|
bool queue = false;
|
bool queue = false;
|
|
|
// now handle the functions
|
// now handle the functions
|
if (fu == kRKCS_CRESET) { // Control reset -----------------
|
if (fu == kRKCS_CRESET) { // Control reset -----------------
|
|
fStats.Inc(kStatNFuncCreset);
|
cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_CRESET);
|
cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_CRESET);
|
fRd_busy = false;
|
fRd_busy = false;
|
|
|
} else if (fu == kRKCS_WRITE) { // Write -------------------------
|
} else if (fu == kRKCS_WRITE) { // Write -------------------------
|
// Note: WRITE+FMT is just WRITE
|
// Note: WRITE+FMT is just WRITE
|
|
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;
|
if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE; // not yet supported FIXME
|
if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE; // not yet supported FIXME
|
queue = true;
|
queue = true;
|
|
|
} else if (fu == kRKCS_READ) { // Read --------------------------
|
} else if (fu == kRKCS_READ) { // Read --------------------------
|
|
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; // not yet supported FIXME
|
if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE; // not yet supported FIXME
|
queue = true;
|
queue = true;
|
|
|
} else if (fu == kRKCS_WCHK) { // Write Check -------------------
|
} else if (fu == kRKCS_WCHK) { // Write Check -------------------
|
|
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; // not yet supported FIXME
|
if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE; // not yet supported FIXME
|
queue = true;
|
queue = true;
|
|
|
} else if (fu == kRKCS_SEEK) { // Seek --------------------------
|
} else if (fu == kRKCS_SEEK) { // Seek --------------------------
|
|
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);
|
cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_SBCLR | (1u<<dr));
|
cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_SBCLR | (1u<<dr));
|
Line 415... |
Line 434... |
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 == kRKCS_RCHK) { // Read Check --------------------
|
|
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; // not yet supported FIXME
|
if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE; // not yet supported FIXME
|
queue = true;
|
queue = true;
|
|
|
} else if (fu == kRKCS_DRESET) { // Drive Reset -------------------
|
} else if (fu == kRKCS_DRESET) { // Drive Reset -------------------
|
|
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 == kRKCS_WLOCK) { // Write Lock --------------------
|
|
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);
|
cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
|
cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
|
Line 470... |
Line 492... |
|
|
uint8_t buf[512];
|
uint8_t buf[512];
|
|
|
if (fu == kRKCS_WRITE) { // Write -------------------------
|
if (fu == kRKCS_WRITE) { // Write -------------------------
|
// Note: WRITE+FMT is like WRITE
|
// Note: WRITE+FMT is like WRITE
|
|
fStats.Inc(kStatNRdmaWrite);
|
RlinkCommandList clist;
|
RlinkCommandList clist;
|
size_t bsize = (fRd_nwrd>256) ? 256 : fRd_nwrd;
|
size_t bsize = (fRd_nwrd>256) ? 256 : fRd_nwrd;
|
cpu.AddRMem(clist, fRd_addr, (uint16_t*) buf, bsize,
|
cpu.AddRMem(clist, fRd_addr, (uint16_t*) buf, bsize,
|
Rw11Cpu::kCp_ah_m_22bit|Rw11Cpu::kCp_ah_m_ubmap);
|
Rw11Cpu::kCp_ah_m_22bit|Rw11Cpu::kCp_ah_m_ubmap);
|
Server().Exec(clist);
|
Server().Exec(clist);
|
Line 492... |
Line 515... |
}
|
}
|
if (rker==0 && fRd_nwrd>0) // not error and not yet done
|
if (rker==0 && fRd_nwrd>0) // not error and not yet done
|
return 1; // requeue
|
return 1; // requeue
|
|
|
} else if (fu == kRKCS_READ) {
|
} else if (fu == kRKCS_READ) {
|
|
fStats.Inc(kStatNRdmaRead);
|
if ((fRd_rkcs&kRKCS_M_FMT) == 0) { // Read --------------------------
|
if ((fRd_rkcs&kRKCS_M_FMT) == 0) { // Read --------------------------
|
RerrMsg emsg;
|
RerrMsg emsg;
|
bool rc = unit.VirtRead(fRd_lba, 1, buf, emsg);
|
bool rc = unit.VirtRead(fRd_lba, 1, buf, emsg);
|
if (!rc) {
|
if (!rc) {
|
RlogMsg lmsg(LogFile());
|
RlogMsg lmsg(LogFile());
|
Line 531... |
Line 555... |
if (rker==0 && fRd_nwrd>0) // not error and not yet done
|
if (rker==0 && fRd_nwrd>0) // not error and not yet done
|
return 1; // requeue
|
return 1; // requeue
|
}
|
}
|
|
|
} else if (fu == kRKCS_WCHK) { // Write Check -------------------
|
} else if (fu == kRKCS_WCHK) { // Write Check -------------------
|
|
fStats.Inc(kStatNRdmaWchk);
|
uint16_t bufmem[256];
|
uint16_t bufmem[256];
|
RlinkCommandList clist;
|
RlinkCommandList clist;
|
size_t bsize = (fRd_nwrd>256) ? 256 : fRd_nwrd;
|
size_t bsize = (fRd_nwrd>256) ? 256 : fRd_nwrd;
|
cpu.AddRMem(clist, fRd_addr, bufmem, bsize,
|
cpu.AddRMem(clist, fRd_addr, bufmem, bsize,
|
Rw11Cpu::kCp_ah_m_22bit|Rw11Cpu::kCp_ah_m_ubmap);
|
Rw11Cpu::kCp_ah_m_22bit|Rw11Cpu::kCp_ah_m_ubmap);
|
Line 563... |
Line 588... |
if (!stop && fRd_nwrd>0) // not error and not yet done
|
if (!stop && fRd_nwrd>0) // not error and not yet done
|
return 1; // requeue
|
return 1; // requeue
|
|
|
} else if (fu == kRKCS_RCHK) { // Read Check --------------------
|
} else if (fu == kRKCS_RCHK) { // Read Check --------------------
|
// Note: no DMA transfer done; done here to keep logic similar to read
|
// Note: no DMA transfer done; done here to keep logic similar to read
|
|
fStats.Inc(kStatNRdmaRchk);
|
size_t bsize = (fRd_nwrd>256) ? 256 : fRd_nwrd;
|
size_t bsize = (fRd_nwrd>256) ? 256 : fRd_nwrd;
|
fRd_nwrd -= bsize;
|
fRd_nwrd -= bsize;
|
fRd_addr += 2*bsize;
|
fRd_addr += 2*bsize;
|
fRd_lba += 1;
|
fRd_lba += 1;
|
if (rker==0 && fRd_nwrd>0) // not error and not yet done
|
if (rker==0 && fRd_nwrd>0) // not error and not yet done
|
return 1; // requeue
|
return 1; // requeue
|
|
|
} else {
|
} else {
|
throw Rexception("Rw11CntlDL11::RdmaHandler",
|
throw Rexception("Rw11CntlRK11::RdmaHandler",
|
"Bad state: bad function code");
|
"Bad state: bad function code");
|
}
|
}
|
|
|
// common handling for dma transfer completion
|
// common handling for dma transfer completion
|
if (fRd_ovr) rker |= kRKER_M_OVR;
|
if (fRd_ovr) rker |= kRKER_M_OVR;
|