OpenCores
URL https://opencores.org/ocsvn/w11/w11/trunk

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.7/] [tools/] [src/] [librw11/] [Rw11CntlTM11.cpp] - Rev 33

Compare with Previous | Blame | View Log

// $Id: Rw11CntlTM11.cpp 690 2015-06-07 18:23:51Z mueller $
//
// Copyright 2015- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
// Other credits: 
//   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
// 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.
//
// This program 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 complete details.
// 
// Revision History: 
// Date         Rev Version  Comment
// 2015-06-06   690   1.0.1  BUGFIX: AddFastExit() check for Virt() defined
// 2015-06-04   686   1.0    Initial version
// 2015-05-17   683   0.1    First draft
// ---------------------------------------------------------------------------
 
/*!
  \file
  \version $Id: Rw11CntlTM11.cpp 690 2015-06-07 18:23:51Z mueller $
  \brief   Implemenation of Rw11CntlTM11.
*/
 
#include "boost/bind.hpp"
#include "boost/foreach.hpp"
#define foreach_ BOOST_FOREACH
 
#include "librtools/RosFill.hpp"
#include "librtools/RosPrintBvi.hpp"
#include "librtools/RosPrintf.hpp"
#include "librtools/Rexception.hpp"
#include "librtools/RlogMsg.hpp"
 
#include "Rw11CntlTM11.hpp"
 
using namespace std;
 
/*!
  \class Retro::Rw11CntlTM11
  \brief FIXME_docs
*/
 
// all method definitions in namespace Retro
namespace Retro {
 
//------------------------------------------+-----------------------------------
// constants definitions
 
const uint16_t Rw11CntlTM11::kIbaddr;
const int      Rw11CntlTM11::kLam;
 
const uint16_t Rw11CntlTM11::kTMSR; 
const uint16_t Rw11CntlTM11::kTMCR; 
const uint16_t Rw11CntlTM11::kTMBC; 
const uint16_t Rw11CntlTM11::kTMBA; 
const uint16_t Rw11CntlTM11::kTMDB; 
const uint16_t Rw11CntlTM11::kTMRL; 
 
const uint16_t Rw11CntlTM11::kProbeOff;
const bool     Rw11CntlTM11::kProbeInt;
const bool     Rw11CntlTM11::kProbeRem;
 
const uint16_t Rw11CntlTM11::kTMSR_M_ICMD;
const uint16_t Rw11CntlTM11::kTMSR_M_EOF;
const uint16_t Rw11CntlTM11::kTMSR_M_PAE;
const uint16_t Rw11CntlTM11::kTMSR_M_EOT;
const uint16_t Rw11CntlTM11::kTMSR_M_RLE;
const uint16_t Rw11CntlTM11::kTMSR_M_BTE;
const uint16_t Rw11CntlTM11::kTMSR_M_NXM;
const uint16_t Rw11CntlTM11::kTMSR_M_ONL;
const uint16_t Rw11CntlTM11::kTMSR_M_BOT;
const uint16_t Rw11CntlTM11::kTMSR_M_WRL;
const uint16_t Rw11CntlTM11::kTMSR_M_REW;
const uint16_t Rw11CntlTM11::kTMSR_M_TUR;
 
const uint16_t Rw11CntlTM11::kTMCR_V_ERR;
const uint16_t Rw11CntlTM11::kTMCR_V_DEN;
const uint16_t Rw11CntlTM11::kTMCR_B_DEN;
const uint16_t Rw11CntlTM11::kTMCR_V_UNIT;
const uint16_t Rw11CntlTM11::kTMCR_B_UNIT;
const uint16_t Rw11CntlTM11::kTMCR_M_RDY;
const uint16_t Rw11CntlTM11::kTMCR_V_EA;
const uint16_t Rw11CntlTM11::kTMCR_B_EA;
const uint16_t Rw11CntlTM11::kTMCR_V_FUNC;
const uint16_t Rw11CntlTM11::kTMCR_B_FUNC;
const uint16_t Rw11CntlTM11::kTMCR_M_GO;
 
const uint16_t Rw11CntlTM11::kFUNC_UNLOAD;
const uint16_t Rw11CntlTM11::kFUNC_READ;
const uint16_t Rw11CntlTM11::kFUNC_WRITE ;
const uint16_t Rw11CntlTM11::kFUNC_WEOF;
const uint16_t Rw11CntlTM11::kFUNC_SFORW;
const uint16_t Rw11CntlTM11::kFUNC_SBACK;
const uint16_t Rw11CntlTM11::kFUNC_WEIRG;
const uint16_t Rw11CntlTM11::kFUNC_REWIND;
 
const uint16_t Rw11CntlTM11::kRFUNC_WUNIT;
const uint16_t Rw11CntlTM11::kRFUNC_DONE;
 
const uint16_t Rw11CntlTM11::kTMCR_M_RICMD;
const uint16_t Rw11CntlTM11::kTMCR_M_RPAE;
const uint16_t Rw11CntlTM11::kTMCR_M_RRLE;
const uint16_t Rw11CntlTM11::kTMCR_M_RBTE;
const uint16_t Rw11CntlTM11::kTMCR_M_RNXM;
const uint16_t Rw11CntlTM11::kTMCR_M_REAENA;
const uint16_t Rw11CntlTM11::kTMCR_V_REA;
const uint16_t Rw11CntlTM11::kTMCR_B_REA;
 
const uint16_t Rw11CntlTM11::kTMRL_M_EOF;
const uint16_t Rw11CntlTM11::kTMRL_M_EOT;
const uint16_t Rw11CntlTM11::kTMRL_M_ONL;
const uint16_t Rw11CntlTM11::kTMRL_M_BOT;
const uint16_t Rw11CntlTM11::kTMRL_M_WRL;
const uint16_t Rw11CntlTM11::kTMRL_M_REW;
 
//------------------------------------------+-----------------------------------
//! Default constructor
 
Rw11CntlTM11::Rw11CntlTM11()
  : Rw11CntlBase<Rw11UnitTM11,4>("tm11"),
    fPC_tmcr(0),
    fPC_tmsr(0),
    fPC_tmbc(0),
    fPC_tmba(0),
    fRd_tmcr(0),
    fRd_tmsr(0), 
    fRd_tmbc(0), 
    fRd_tmba(0), 
    fRd_bc(0),
    fRd_addr(0),
    fRd_nwrd(0),
    fRd_fu(0),
    fRd_opcode(0),
    fBuf(),
    fRdma(this,
          boost::bind(&Rw11CntlTM11::RdmaPreExecCB,  this, _1, _2, _3, _4),
          boost::bind(&Rw11CntlTM11::RdmaPostExecCB, this, _1, _2, _3, _4))
{
  // must be here because Units have a back-ptr (not available at Rw11CntlBase)
  for (size_t i=0; i<NUnit(); i++) {
    fspUnit[i].reset(new Rw11UnitTM11(this, i));
  }
 
  fStats.Define(kStatNFuncUnload , "NFuncUnload"  , "func UNLOAD");
  fStats.Define(kStatNFuncRead   , "NFuncRead"    , "func READ");
  fStats.Define(kStatNFuncWrite  , "NFuncWrite"   , "func WRITE");
  fStats.Define(kStatNFuncWeof   , "NFuncWeof"    , "func WEOF");
  fStats.Define(kStatNFuncSforw  , "NFuncSforw"   , "func SFORW");
  fStats.Define(kStatNFuncSback  , "NFuncSback"   , "func SBACK");
  fStats.Define(kStatNFuncWrteg  , "NFuncWrteg"   , "func WRTEG");
  fStats.Define(kStatNFuncRewind , "NFuncRewind"  , "func REWIND");
}
 
//------------------------------------------+-----------------------------------
//! Destructor
 
Rw11CntlTM11::~Rw11CntlTM11()
{}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlTM11::Config(const std::string& name, uint16_t base, int lam)
{
  ConfigCntl(name, base, lam, kProbeOff, kProbeInt, kProbeRem);
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlTM11::Start()
{
  if (fStarted || fLam<0 || !fEnable || !fProbe.Found())
    throw Rexception("Rw11CntlTM11::Start",
                     "Bad state: started, no lam, not enable, not found");
 
  // add device register address ibus and rbus mappings
  // done here because now Cntl bound to Cpu and Cntl probed
  Cpu().AllIAddrMapInsert(Name()+".sr", Base() + kTMSR);
  Cpu().AllIAddrMapInsert(Name()+".cr", Base() + kTMCR);
  Cpu().AllIAddrMapInsert(Name()+".bc", Base() + kTMBC);
  Cpu().AllIAddrMapInsert(Name()+".ba", Base() + kTMBA);
  Cpu().AllIAddrMapInsert(Name()+".db", Base() + kTMDB);
  Cpu().AllIAddrMapInsert(Name()+".rl", Base() + kTMRL);
 
  // setup primary info clist
  fPrimClist.Clear();
  fPrimClist.AddAttn();
  fPC_tmcr = Cpu().AddRibr(fPrimClist, fBase+kTMCR);
  fPC_tmsr = Cpu().AddRibr(fPrimClist, fBase+kTMSR);
  fPC_tmbc = Cpu().AddRibr(fPrimClist, fBase+kTMBC);
  fPC_tmba = Cpu().AddRibr(fPrimClist, fBase+kTMBA);
 
  // add attn handler
  Server().AddAttnHandler(boost::bind(&Rw11CntlTM11::AttnHandler, this, _1), 
                          uint16_t(1)<<fLam, (void*)this);
 
  fStarted = true;
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlTM11::UnitSetup(size_t ind)
{
  Rw11UnitTM11& unit = *fspUnit[ind];
  Rw11Cpu& cpu  = Cpu();
  RlinkCommandList clist;
 
  uint16_t tmds = 0;
  if (unit.Virt()) {                        // file attached
    tmds |= kTMRL_M_ONL;
    if (unit.Virt()->WProt()) tmds |= kTMRL_M_WRL;
    if (unit.Virt()->Bot())   tmds |= kTMRL_M_BOT;
  }
  unit.SetTmds(tmds);
  cpu.AddWibr(clist, fBase+kTMCR, (uint16_t(ind)<<kTMCR_V_RUNIT)|
                                  (kRFUNC_WUNIT<<kTMCR_V_FUNC) );
  cpu.AddWibr(clist, fBase+kTMRL, tmds);
  Server().Exec(clist);
 
  return;
}  
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
bool Rw11CntlTM11::BootCode(size_t unit, std::vector<uint16_t>& code, 
                            uint16_t& aload, uint16_t& astart)
{
  uint16_t kBOOT_START = 02000;
  uint16_t bootcode[] = {      // tm11 boot loader - from simh pdp11_tm.c (v3.9)
    0046524,                   // boot_start: "TM" 
    0012706, kBOOT_START,      // mov #boot_start, sp 
    0012700, uint16_t(unit),   // mov #unit_num, r0 
    0012701, 0172526,          // mov #172526, r1      ; #tmba
    0005011,                   // clr (r1)             ; tmba = 0
    0012741, 0177777,          // mov #-1, -(r1)       ; tmbc = -1
    0010002,                   // mov r0,r2 
    0000302,                   // swab r2 
    0062702, 0060011,          // add #60011, r2 
    0010241,                   // mov r2, -(r1)        ; tmcr = space + go 
    0105711,                   // tstb (r1)            ; test tmcr.rdy
    0100376,                   // bpl .-2 
    0010002,                   // mov r0,r2            ; note: tmbc=0 now
    0000302,                   // swab r2 
    0062702, 0060003,          // add #60003, r2       ; note: tmbc still = 0!
    0010211,                   // mov r2, (r1)         ; tmcr = read + go 
    0105711,                   // tstb (r1)            ; test tmcr.rdy
    0100376,                   // bpl .-2 
    0005002,                   // clr r2 
    0005003,                   // clr r3 
    0012704, uint16_t(kBOOT_START+020),   // mov #boot_start+20, r4 
    0005005,                   // clr r5 
    0005007                    // clr r7 
  };
 
  code.clear();
  foreach_ (uint16_t& w, bootcode) code.push_back(w); 
  aload  = kBOOT_START;
  astart = kBOOT_START+2;
  return true;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlTM11::Dump(std::ostream& os, int ind, const char* text) const
{
  RosFill bl(ind);
  os << bl << (text?text:"--") << "Rw11CntlTM11 @ " << this << endl;
  os << bl << "  fPC_tmcr:        " << RosPrintf(fPC_tmcr,"d",6) << endl;
  os << bl << "  fPC_tmsr:        " << RosPrintf(fPC_tmsr,"d",6) << endl;
  os << bl << "  fPC_tmbc:        " << RosPrintf(fPC_tmbc,"d",6) << endl;
  os << bl << "  fPC_tmba:        " << RosPrintf(fPC_tmba,"d",6) << endl;
  os << bl << "  fRd_tmcr:        " << RosPrintBvi(fRd_tmcr,8) << endl;
  os << bl << "  fRd_tmsr:        " << RosPrintBvi(fRd_tmsr,8) << endl;
  os << bl << "  fRd_tmbc:        " << RosPrintBvi(fRd_tmbc,8) << endl;
  os << bl << "  fRd_tmba:        " << RosPrintBvi(fRd_tmba,8) << endl;
  os << bl << "  fRd_bc:          " << RosPrintf(fRd_bc,"d",6) << endl;
  os << bl << "  fRd_addr:        " << RosPrintBvi(fRd_addr,8,18) << endl;
  os << bl << "  fRd_nwrd:        " << RosPrintf(fRd_nwrd,"d",6) << endl;
  os << bl << "  fRd_fu:          " << fRd_fu  << endl;
  os << bl << "  fRd_opcode:      " << fRd_opcode  << endl;
  os << bl << "  fBuf.size()      " << RosPrintf(fBuf.size(),"d",6) << endl;
  fRdma.Dump(os, ind+2, "fRdma: ");
  Rw11CntlBase<Rw11UnitTM11,4>::Dump(os, ind, " ^");
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int Rw11CntlTM11::AttnHandler(RlinkServer::AttnArgs& args)
{
  fStats.Inc(kStatNAttnHdl);
  Server().GetAttnInfo(args, fPrimClist);
 
  uint16_t tmcr = fPrimClist[fPC_tmcr].Data();
  uint16_t tmsr = fPrimClist[fPC_tmsr].Data();
  uint16_t tmbc = fPrimClist[fPC_tmbc].Data();
  uint16_t tmba = fPrimClist[fPC_tmba].Data();
 
  uint16_t unum = (tmcr>>kTMCR_V_UNIT)  & kTMCR_B_UNIT;
  uint16_t ea   = (tmcr>>kTMCR_V_EA)    & kTMCR_B_EA;
  uint16_t fu   = (tmcr>>kTMCR_V_FUNC)  & kTMCR_B_FUNC;
 
  uint32_t addr = uint32_t(ea)<<16 | uint32_t(tmba);
 
  // Note: a zero tmbc translates into nbyt=64k !
  //       correct behaviour, the boot loaded actually issues a read
  //       with tmbc=0 to read the boot block into memory !!
  uint32_t nbyt = (~uint32_t(tmbc)&0xffff) + 1; // transfer size in bytes
 
  //Rw11Cpu& cpu = Cpu();
  RlinkCommandList clist;
 
  if (fTraceLevel>0) {
    RlogMsg lmsg(LogFile());
    static const char* fumnemo[8] = 
      {"un ","rd ","wr ","we ","sf ","sb ","wi ","re "};
    lmsg << "-I TM11"
         << " fu=" << fumnemo[fu&07]
         << " un=" << unum
         << " cr=" << RosPrintBvi(tmcr,8)
         << " ad=" << RosPrintBvi(addr,8,18)
         << " bc=" << RosPrintBvi(tmbc,8)
         << " nb=";
    if (nbyt==65536) lmsg << "  (0)"; else lmsg << RosPrintf(nbyt,"d",5);
  }
 
  // check for spurious interrupts (either RDY=1 or RDY=0 and rdma busy)
  if ((tmcr & kTMCR_M_RDY) || fRdma.IsActive()) {
    RlogMsg lmsg(LogFile());
    lmsg << "-E TM11   err "
         << " cr=" << RosPrintBvi(tmcr,8)
         << " spurious lam: "
         << (fRdma.IsActive() ? "RDY=0 and Rdma busy" : "RDY=1");
    return 0;
  }
 
  // check for general abort conditions: invalid unit number
  if (unum > NUnit()) {
    AddErrorExit(clist, kTMCR_M_RICMD);
    Server().Exec(clist);
    return 0;
  }
 
  Rw11UnitTM11& unit = *fspUnit[unum];
 
  // check for general abort conditions: 
  //  - unit not attached
  //  - write to a write locked unit
  bool wcmd = fu == kFUNC_WRITE ||
              fu == kFUNC_WEIRG ||
              fu == kFUNC_WEOF;
 
  if ((!unit.Virt()) || (wcmd && unit.Virt()->WProt()) ) {
    AddErrorExit(clist, kTMCR_M_RICMD);
    Server().Exec(clist);
    return 0;
  }
 
  // remember request parameters for call back and error exit handling
  fRd_tmcr = tmcr;
  fRd_tmsr = tmsr;
  fRd_tmbc = tmbc;
  fRd_tmba = tmba;
  fRd_addr = addr;
  fRd_fu   = fu;
 
  // now handle the functions
  int      opcode = Rw11VirtTape::kOpCodeOK;
  RerrMsg  emsg;
 
  if (fu == kFUNC_UNLOAD) {                 // Unload ------------------------
    fStats.Inc(kStatNFuncUnload);
    unit.Detach();
    AddFastExit(clist, opcode, 0);
    RlogMsg lmsg(LogFile());
    lmsg << "-I TM11"
         << " unit " << unum << "unload";
 
  } else if (fu == kFUNC_READ) {            // Read --------------------------
    fStats.Inc(kStatNFuncRead);
    size_t nwalloc = (nbyt+1)/2;
    if (fBuf.size() < nwalloc) fBuf.resize(nwalloc);
    size_t ndone;
    bool rc = unit.VirtReadRecord(nbyt, reinterpret_cast<uint8_t*>(fBuf.data()),
                                  ndone, fRd_opcode, emsg);
    if (!rc) WriteLog("read", emsg);
    if ((!rc) || ndone == 0) {
      AddFastExit(clist, fRd_opcode, 0);
    } else if (ndone&0x1) {                 // FIXME_code: add odd rlen handling
      AddErrorExit(clist, kTMCR_M_RICMD|kTMSR_M_BTE);   // now just bail out !!
    } else {
      size_t nwdma = ndone/2;
      fRdma.QueueWMem(addr, fBuf.data(), nwdma, 
                      Rw11Cpu::kCPAH_M_22BIT|Rw11Cpu::kCPAH_M_UBMAP);
    }
 
  } else if (fu == kFUNC_WRITE ||           // Write -------------------------
             fu == kFUNC_WEIRG) {
    fStats.Inc((fu==kFUNC_WRITE) ? kStatNFuncWrite : kStatNFuncWrteg);
    size_t nwdma = (nbyt+1)/2;
    if (fBuf.size() < nwdma) fBuf.resize(nwdma);
    if (nbyt&0x1) {                         // FIXME_code: add odd rlen handling
      AddErrorExit(clist, kTMCR_M_RICMD|kTMSR_M_BTE);   // now just bail out !!
    } else {
      fRdma.QueueRMem(addr, fBuf.data(), nwdma, 
                      Rw11Cpu::kCPAH_M_22BIT|Rw11Cpu::kCPAH_M_UBMAP);
    }
 
  } else if (fu == kFUNC_WEOF) {            // Write Eof ---------------------
    fStats.Inc(kStatNFuncWeof);
    if (!unit.VirtWriteEof(emsg)) WriteLog("weof", emsg);
    AddFastExit(clist, opcode, 0);
 
  } else if (fu == kFUNC_SFORW) {           // Space forward -----------------
    fStats.Inc(kStatNFuncSforw);
    size_t ndone;
    if (!unit.VirtSpaceForw(nbyt, ndone, opcode, emsg)) WriteLog("sback", emsg);
    AddFastExit(clist, opcode, ndone);
 
  } else if (fu == kFUNC_SBACK) {           // Space Backward ----------------
    fStats.Inc(kStatNFuncSback);
    size_t ndone;
    if (!unit.VirtSpaceBack(nbyt, ndone, opcode, emsg)) WriteLog("sback", emsg);
    AddFastExit(clist, opcode, ndone);
 
  } else if (fu == kFUNC_REWIND) {          // Rewind ------------------------
    fStats.Inc(kStatNFuncRewind);
    if (!unit.VirtRewind(opcode, emsg)) WriteLog("rewind", emsg);
    AddFastExit(clist, opcode, 0);
  }
 
  if (clist.Size()) {                       // if handled directly
    Server().Exec(clist);                   // doit
  }
 
  return 0;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlTM11::RdmaPreExecCB(int stat, size_t nwdone, size_t nwnext,
                                 RlinkCommandList& clist)
{
  // noop for TM11
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlTM11::RdmaPostExecCB(int stat, size_t ndone,
                                  RlinkCommandList& clist, size_t ncmd)
{
  if (stat == Rw11Rdma::kStatusBusy) return;
 
  uint16_t tmcr = 0;
  // handle Rdma aborts
  if (stat == Rw11Rdma::kStatusFailRdma) tmcr |= kTMCR_M_RNXM;
 
  // finally to TM11 register update
  RlinkCommandList clist1;
  AddNormalExit(clist1, ndone, tmcr);
  Server().Exec(clist1);
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlTM11::AddErrorExit(RlinkCommandList& clist, uint16_t tmcr)
{
  Rw11Cpu& cpu = Cpu();
 
  tmcr |= (kRFUNC_DONE<<kTMCR_V_FUNC);
  cpu.AddWibr(clist, fBase+kTMCR, tmcr);
  if (fTraceLevel>1) {
    RlogMsg lmsg(LogFile());
    lmsg << "-I TM11"
         << "   err "
         << "     "
         << " cr=" << RosPrintBvi(tmcr,8);
  }
 
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlTM11::AddFastExit(RlinkCommandList& clist, int opcode, size_t ndone)
{
  uint16_t unum = (fRd_tmcr>>kTMCR_V_UNIT)  & kTMCR_B_UNIT;
  Rw11UnitTM11& unit = *fspUnit[unum];
  Rw11Cpu& cpu = Cpu();
 
  uint16_t tmcr = 0;
  uint16_t tmds = 0;
 
  // AddFastExit() is also called after UNLOAD, which calls unit.Detach()
  // So unlike in all other cases, Virt() may be 0, so check on this
  if (unit.Virt()) {
    tmds |= kTMRL_M_ONL;
    if (unit.Virt()->WProt()) tmds |= kTMRL_M_WRL;
    if (unit.Virt()->Bot())   tmds |= kTMRL_M_BOT;
    if (unit.Virt()->Eot())   tmds |= kTMRL_M_EOT;
  }
 
  switch (opcode) {
 
  case Rw11VirtTape::kOpCodeOK: 
  case Rw11VirtTape::kOpCodeBot:
    break;
 
  case Rw11VirtTape::kOpCodeEof:
    tmds |= kTMRL_M_EOF;
    break;
 
  default:
    tmcr |= kTMCR_M_RBTE;
    break;
  }
 
  uint16_t tmbc = fRd_tmbc + uint16_t(ndone);
 
  unit.SetTmds(tmds);
  cpu.AddWibr(clist, fBase+kTMCR, (uint16_t(unum)<<kTMCR_V_RUNIT)|
                                  (kRFUNC_WUNIT<<kTMCR_V_FUNC) );
  cpu.AddWibr(clist, fBase+kTMRL, tmds);
  if (ndone) cpu.AddWibr(clist, fBase+kTMBC, tmbc);
  tmcr |= (kRFUNC_DONE<<kTMCR_V_FUNC);
  cpu.AddWibr(clist, fBase+kTMCR, tmcr);
 
 if (fTraceLevel>1) {
    RlogMsg lmsg(LogFile());
    bool err = tmcr & (kTMCR_M_RBTE);
    lmsg << "-I TM11"
         << (err ? "   err " :"    ok ")
         << " un=" << unum
         << " cr=" << RosPrintBvi(tmcr,8)
         << "          "
         << " bc=" << RosPrintBvi(tmbc,8)
         << " ds=" << RosPrintBvi(tmds,8);
  }
 
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlTM11::AddNormalExit(RlinkCommandList& clist, size_t ndone,
                                 uint16_t tmcr)
{
  uint16_t unum = (fRd_tmcr>>kTMCR_V_UNIT)  & kTMCR_B_UNIT;
  Rw11UnitTM11& unit = *fspUnit[unum];
  Rw11Cpu& cpu = Cpu();
 
  uint16_t tmds = kTMRL_M_ONL;
  if (unit.Virt()->WProt()) tmds |= kTMRL_M_WRL;
  if (unit.Virt()->Bot())   tmds |= kTMRL_M_BOT;
  if (unit.Virt()->Eot())   tmds |= kTMRL_M_EOT;
 
  uint32_t addr = fRd_addr + 2*ndone;
  uint16_t tmbc = fRd_tmbc + 2*uint16_t(ndone);
 
  if (fRd_fu == kFUNC_READ) {               // handle READ
    switch (fRd_opcode) {
 
    case Rw11VirtTape::kOpCodeOK: 
      break;
 
    case Rw11VirtTape::kOpCodeRecLenErr:
      tmcr |= kTMCR_M_RRLE;
      break;
 
    case Rw11VirtTape::kOpCodeBadParity:
      tmcr |= kTMCR_M_RPAE;
      break;
 
    default:
      tmcr |= kTMCR_M_RBTE;
      break;
    }
 
  } else {                                  // handle WRITE or WEIRG
    int opcode;
    RerrMsg emsg;
    size_t nbyt = 2*ndone;
    if (!unit.VirtWriteRecord(nbyt, reinterpret_cast<uint8_t*>(fBuf.data()), 
                              opcode, emsg)) 
      WriteLog("write", emsg);
  }
 
  uint16_t tmba = uint16_t(addr & 0xfffe);
  uint16_t ea   = uint16_t((addr>>16)&0x0003);
  tmcr |= kTMCR_M_REAENA | (ea<<kTMCR_V_REA);
 
  unit.SetTmds(tmds);
  cpu.AddWibr(clist, fBase+kTMCR, (uint16_t(unum)<<kTMCR_V_RUNIT)|
                                  (kRFUNC_WUNIT<<kTMCR_V_FUNC) );
  cpu.AddWibr(clist, fBase+kTMRL, tmds);
  cpu.AddWibr(clist, fBase+kTMBC, tmbc);
  cpu.AddWibr(clist, fBase+kTMBA, tmba);
  tmcr |= (kRFUNC_DONE<<kTMCR_V_FUNC);
  cpu.AddWibr(clist, fBase+kTMCR, tmcr);
 
 if (fTraceLevel>1) {
    RlogMsg lmsg(LogFile());
    bool err = tmcr & (kTMCR_M_RPAE|kTMCR_M_RRLE|kTMCR_M_RBTE|kTMCR_M_RNXM);
    lmsg << "-I TM11"
         << (err ? "   err " :"    ok ")
         << " un=" << unum
         << " cr=" << RosPrintBvi(tmcr,8)
         << " ad=" << RosPrintBvi(addr,8,18)
         << " bc=" << RosPrintBvi(tmbc,8) 
         << " ds=" << RosPrintBvi(tmds,8);
  }
 
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlTM11::WriteLog(const char* func, RerrMsg&  emsg)
{
  RlogMsg lmsg(LogFile());
  lmsg << "-E TM11"
       << " error for func=" << func
       << ":" << emsg;
 
  return;
}
 
 
} // end namespace Retro
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.