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

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.74/] [tools/] [src/] [librw11/] [Rw11CntlRK11.cpp] - Rev 31

Go to most recent revision | Compare with Previous | Blame | View Log

// $Id: Rw11CntlRK11.cpp 686 2015-06-04 21:08:08Z mueller $
//
// Copyright 2013-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-04   686   2.0.2  check for spurious lams
// 2015-02-17   647   2.0.1  use Nwrd2Nblk(); BUGFIX: revise RdmaPostExecCB()
// 2015-01-04   628   2.0    use Rw11RdmaDisk
// 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-06-14   562   1.0.1  Add stats
// 2013-04-20   508   1.0    Initial version
// 2013-02-10   485   0.1    First draft
// ---------------------------------------------------------------------------
 
/*!
  \file
  \version $Id: Rw11CntlRK11.cpp 686 2015-06-04 21:08:08Z mueller $
  \brief   Implemenation of Rw11CntlRK11.
*/
 
#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 "Rw11CntlRK11.hpp"
 
using namespace std;
 
/*!
  \class Retro::Rw11CntlRK11
  \brief FIXME_docs
*/
 
// all method definitions in namespace Retro
namespace Retro {
 
//------------------------------------------+-----------------------------------
// constants definitions
 
const uint16_t Rw11CntlRK11::kIbaddr;
const int      Rw11CntlRK11::kLam;
 
const uint16_t Rw11CntlRK11::kRKDS; 
const uint16_t Rw11CntlRK11::kRKER; 
const uint16_t Rw11CntlRK11::kRKCS; 
const uint16_t Rw11CntlRK11::kRKWC; 
const uint16_t Rw11CntlRK11::kRKBA; 
const uint16_t Rw11CntlRK11::kRKDA; 
const uint16_t Rw11CntlRK11::kRKMR; 
 
const uint16_t Rw11CntlRK11::kProbeOff;
const bool     Rw11CntlRK11::kProbeInt;
const bool     Rw11CntlRK11::kProbeRem;
 
const uint16_t Rw11CntlRK11::kRKDS_M_ID;
const uint16_t Rw11CntlRK11::kRKDS_V_ID;
const uint16_t Rw11CntlRK11::kRKDS_B_ID;
const uint16_t Rw11CntlRK11::kRKDS_M_HDEN;
const uint16_t Rw11CntlRK11::kRKDS_M_DRU;
const uint16_t Rw11CntlRK11::kRKDS_M_SIN;
const uint16_t Rw11CntlRK11::kRKDS_M_SOK;
const uint16_t Rw11CntlRK11::kRKDS_M_DRY;
const uint16_t Rw11CntlRK11::kRKDS_M_ADRY;
const uint16_t Rw11CntlRK11::kRKDS_M_WPS;
const uint16_t Rw11CntlRK11::kRKDS_B_SC;
 
const uint16_t Rw11CntlRK11::kRKER_M_DRE;
const uint16_t Rw11CntlRK11::kRKER_M_OVR;
const uint16_t Rw11CntlRK11::kRKER_M_WLO;
const uint16_t Rw11CntlRK11::kRKER_M_PGE;
const uint16_t Rw11CntlRK11::kRKER_M_NXM;
const uint16_t Rw11CntlRK11::kRKER_M_NXD;
const uint16_t Rw11CntlRK11::kRKER_M_NXC;
const uint16_t Rw11CntlRK11::kRKER_M_NXS;
const uint16_t Rw11CntlRK11::kRKER_M_CSE;
const uint16_t Rw11CntlRK11::kRKER_M_WCE;
 
const uint16_t Rw11CntlRK11::kRKCS_M_MAINT;
const uint16_t Rw11CntlRK11::kRKCS_M_IBA;
const uint16_t Rw11CntlRK11::kRKCS_M_FMT;
const uint16_t Rw11CntlRK11::kRKCS_M_RWA;
const uint16_t Rw11CntlRK11::kRKCS_M_SSE;
const uint16_t Rw11CntlRK11::kRKCS_M_RDY;
const uint16_t Rw11CntlRK11::kRKCS_M_MEX;
const uint16_t Rw11CntlRK11::kRKCS_V_MEX;
const uint16_t Rw11CntlRK11::kRKCS_B_MEX;
const uint16_t Rw11CntlRK11::kRKCS_V_FUNC;
const uint16_t Rw11CntlRK11::kRKCS_B_FUNC;
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_V_DRSEL;
const uint16_t Rw11CntlRK11::kRKDA_B_DRSEL;
const uint16_t Rw11CntlRK11::kRKDA_M_CYL;
const uint16_t Rw11CntlRK11::kRKDA_V_CYL;
const uint16_t Rw11CntlRK11::kRKDA_B_CYL;
const uint16_t Rw11CntlRK11::kRKDA_M_SUR;
const uint16_t Rw11CntlRK11::kRKDA_V_SUR;
const uint16_t Rw11CntlRK11::kRKDA_B_SUR;
const uint16_t Rw11CntlRK11::kRKDA_B_SC;
 
const uint16_t Rw11CntlRK11::kRKMR_M_RID;
const uint16_t Rw11CntlRK11::kRKMR_V_RID;
const uint16_t Rw11CntlRK11::kRKMR_M_CRDONE;
const uint16_t Rw11CntlRK11::kRKMR_M_SBCLR;
const uint16_t Rw11CntlRK11::kRKMR_M_CRESET;
const uint16_t Rw11CntlRK11::kRKMR_M_FDONE;
 
//------------------------------------------+-----------------------------------
//! Default constructor
 
Rw11CntlRK11::Rw11CntlRK11()
  : Rw11CntlBase<Rw11UnitRK11,8>("rk11"),
    fPC_rkwc(0),
    fPC_rkba(0),
    fPC_rkda(0),
    fPC_rkmr(0),
    fPC_rkcs(0),
    fRd_rkcs(0),
    fRd_rkda(0),
    fRd_addr(0),
    fRd_lba(0),
    fRd_nwrd(0),
    fRd_fu(0),
    fRd_ovr(false),
    fRdma(this,
          boost::bind(&Rw11CntlRK11::RdmaPreExecCB,  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)
  for (size_t i=0; i<NUnit(); 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");
}
 
//------------------------------------------+-----------------------------------
//! Destructor
 
Rw11CntlRK11::~Rw11CntlRK11()
{}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlRK11::Config(const std::string& name, uint16_t base, int lam)
{
  ConfigCntl(name, base, lam, kProbeOff, kProbeInt, kProbeRem);
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlRK11::Start()
{
  if (fStarted || fLam<0 || !fEnable || !fProbe.Found())
    throw Rexception("Rw11CntlRK11::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()+".ds", Base() + kRKDS);
  Cpu().AllIAddrMapInsert(Name()+".er", Base() + kRKER);
  Cpu().AllIAddrMapInsert(Name()+".cs", Base() + kRKCS);
  Cpu().AllIAddrMapInsert(Name()+".wc", Base() + kRKWC);
  Cpu().AllIAddrMapInsert(Name()+".ba", Base() + kRKBA);
  Cpu().AllIAddrMapInsert(Name()+".da", Base() + kRKDA);
  Cpu().AllIAddrMapInsert(Name()+".mr", Base() + kRKMR);
 
  // setup primary info clist
  fPrimClist.Clear();
  fPrimClist.AddAttn();
  fPC_rkwc = Cpu().AddRibr(fPrimClist, fBase+kRKWC);
  fPC_rkba = Cpu().AddRibr(fPrimClist, fBase+kRKBA);
  fPC_rkda = Cpu().AddRibr(fPrimClist, fBase+kRKDA);
  fPC_rkmr = Cpu().AddRibr(fPrimClist, fBase+kRKMR); // read to monitor CRDONE
  fPC_rkcs = Cpu().AddRibr(fPrimClist, fBase+kRKCS);
 
  // add attn handler
  Server().AddAttnHandler(boost::bind(&Rw11CntlRK11::AttnHandler, this, _1), 
                          uint16_t(1)<<fLam, (void*)this);
 
  fStarted = true;
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlRK11::UnitSetup(size_t ind)
{
  Rw11UnitRK11& unit = *fspUnit[ind];
  Rw11Cpu& cpu  = Cpu();
  RlinkCommandList clist;
 
  uint16_t rkds = ind<<kRKDS_V_ID;
  if (unit.Virt()) {                        // file attached
    rkds |= kRKDS_M_HDEN;                   // always high density
    rkds |= kRKDS_M_SOK;                    // always sector counter OK ?FIXME?
    rkds |= kRKDS_M_DRY;                    // drive available
    rkds |= kRKDS_M_ADRY;                   // access available
    if (unit.WProt())                       // in case write protected
      rkds |= kRKDS_M_WPS;
  }
  unit.SetRkds(rkds);
  cpu.AddWibr(clist, fBase+kRKDS, rkds);
  Server().Exec(clist);
 
  return;
}  
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
bool Rw11CntlRK11::BootCode(size_t unit, std::vector<uint16_t>& code, 
                            uint16_t& aload, uint16_t& astart)
{
  uint16_t kBOOT_START = 02000;
  uint16_t bootcode[] = {      // rk11 boot loader - from simh pdp11_rk.c (v3.9)
    0042113,                   // "KD"
    0012706, kBOOT_START,      // MOV #boot_start, SP
    0012700, uint16_t(unit),   // MOV #unit, R0        ; unit number
    0010003,                   // MOV R0, R3
    0000303,                   // SWAB R3
    0006303,                   // ASL R3
    0006303,                   // ASL R3
    0006303,                   // ASL R3
    0006303,                   // ASL R3
    0006303,                   // ASL R3
    0012701, 0177412,          // MOV #RKDA, R1        ; rkda
    0010311,                   // MOV R3, (R1)         ; load da
    0005041,                   // CLR -(R1)            ; clear ba
    0012741, 0177000,          // MOV #-256.*2, -(R1)  ; load wc
    0012741, 0000005,          // MOV #READ+GO, -(R1)  ; read & go
    0005002,                   // CLR R2
    0005003,                   // CLR R3
    0012704, uint16_t(kBOOT_START+020),  // MOV #START+20, R4 ; ?? unclear ??
    0005005,                   // CLR R5
    0105711,                   // TSTB (R1)
    0100376,                   // BPL .-4
    0105011,                   // CLRB (R1)
    0005007                    // CLR PC     (5007)
  };
 
  code.clear();
  foreach_ (uint16_t& w, bootcode) code.push_back(w); 
  aload  = kBOOT_START;
  astart = kBOOT_START+2;
  return true;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlRK11::Dump(std::ostream& os, int ind, const char* text) const
{
  RosFill bl(ind);
  os << bl << (text?text:"--") << "Rw11CntlRK11 @ " << this << endl;
  os << bl << "  fPC_rkwc:        " << fPC_rkwc << endl;
  os << bl << "  fPC_rkba:        " << fPC_rkba << endl;
  os << bl << "  fPC_rkda:        " << fPC_rkda << endl;
  os << bl << "  fPC_rkmr:        " << fPC_rkmr << endl;
  os << bl << "  fPC_rkcs:        " << fPC_rkcs << endl;
  os << bl << "  fRd_rkcs:        " << fRd_rkcs << endl;
  os << bl << "  fRd_rkda:        " << fRd_rkda << endl;
  os << bl << "  fRd_addr:        " << fRd_addr << endl;
  os << bl << "  fRd_lba:         " << fRd_lba  << endl;
  os << bl << "  fRd_nwrd:        " << fRd_nwrd << endl;
  os << bl << "  fRd_fu:          " << fRd_fu  << endl;
  os << bl << "  fRd_ovr:         " << fRd_ovr  << endl;
  fRdma.Dump(os, ind+2, "fRdma: ");
  Rw11CntlBase<Rw11UnitRK11,8>::Dump(os, ind, " ^");
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int Rw11CntlRK11::AttnHandler(RlinkServer::AttnArgs& args)
{
  fStats.Inc(kStatNAttnHdl);
  Server().GetAttnInfo(args, fPrimClist);
 
  uint16_t rkwc = fPrimClist[fPC_rkwc].Data();
  uint16_t rkba = fPrimClist[fPC_rkba].Data();
  uint16_t rkda = fPrimClist[fPC_rkda].Data();
  //uint16_t rkmr = fPrimClist[fPC_rkmr].Data();
  uint16_t rkcs = fPrimClist[fPC_rkcs].Data();
 
  uint16_t se   =  rkda                 & kRKDA_B_SC;
  uint16_t hd   = (rkda>>kRKDA_V_SUR)   & kRKDA_B_SUR;
  uint16_t cy   = (rkda>>kRKDA_V_CYL)   & kRKDA_B_CYL;
  uint16_t dr   = (rkda>>kRKDA_V_DRSEL) & kRKDA_B_DRSEL;
 
  bool go       =  rkcs & kRKCS_M_GO;
  uint16_t fu   = (rkcs>>kRKCS_V_FUNC)  & kRKCS_B_FUNC;
  uint16_t mex  = (rkcs>>kRKCS_V_MEX)   & kRKCS_B_MEX;
  uint32_t addr = uint32_t(mex)<<16 | uint32_t(rkba);
 
  // Note: apparently are operands first promoted to 32 bit -> mask after ~ !
  uint32_t nwrd = (~uint32_t(rkwc)&0xffff) + 1; // transfer size in words
 
  if (!go) {
    RlogMsg lmsg(LogFile());
    lmsg << "-I RK11 cs=" << RosPrintBvi(rkcs,8)
         << "  go=0, spurious attn, dropped";
    return 0;
  }
 
  // all 8 units are always available, but check anyway
  if (dr > NUnit())
    throw Rexception("Rw11CntlRK11::AttnHandler","Bad state: dr > NUnit()");
 
  Rw11UnitRK11& unit = *fspUnit[dr];
  Rw11Cpu& cpu = Cpu();
  RlinkCommandList clist;
 
  uint32_t lba  = unit.Chs2Lba(cy,hd,se);
  uint32_t nblk = unit.Nwrd2Nblk(nwrd);
 
  uint16_t rker = 0;
  uint16_t rkds = unit.Rkds();
 
  if (fTraceLevel>0) {
    RlogMsg lmsg(LogFile());
    static const char* fumnemo[8] = {"cr","w ","r ","wc","sk","rc","dr","wl"};
 
    lmsg << "-I RK11 cs=" << RosPrintBvi(rkcs,8)
         << " da=" << RosPrintBvi(rkda,8)
         << " ad=" << RosPrintBvi(addr,8,18)
         << " fu=" << fumnemo[fu&0x7]
         << " pa=" << dr 
         << "," << RosPrintf(cy,"d",3) 
         << "," << hd 
         << "," << RosPrintf(se,"d",2)
         << " la,nw=" << RosPrintf(lba,"d",4) 
         << "," << RosPrintf(nwrd,"d",5);
  }
 
  // check for spurious interrupts (either RDY=1 or RDY=0 and rdma busy)
  if ((rkcs & kRKCS_M_RDY) || fRdma.IsActive()) {
    RlogMsg lmsg(LogFile());
    lmsg << "-E RK11   err "
         << " cr=" << RosPrintBvi(rkcs,8)
         << " spurious lam: "
         << (fRdma.IsActive() ? "RDY=0 and Rdma busy" : "RDY=1");
    return 0;
  }
 
  // check for general abort conditions
  if (fu != kFUNC_CRESET &&                 // function not control reset
      (!unit.Virt())) {                     //   and drive not attached
    rker = kRKER_M_NXD;                     //   --> abort with NXD error
 
  } else if (fu != kFUNC_WRITE &&           // function neither write
             fu != kFUNC_READ &&            //   nor read
             (rkcs & (kRKCS_M_FMT|kRKCS_M_RWA))) { // and FMT or RWA set 
    rker = kRKER_M_PGE;                     //   --> abort with PGE error
  } else if (rkcs & kRKCS_M_RWA) {          // RWA not supported
    rker = kRKER_M_DRE;                     //   --> abort with DRE error
  }
 
  if (rker) {
    cpu.AddWibr(clist, fBase+kRKER, rker);
    if (fu == kFUNC_SEEK || fu == kFUNC_DRESET) 
      cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_SBCLR | (1u<<dr));
    cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
    LogRker(rker);
    Server().Exec(clist);
    return 0;
  }
 
  // check for overrun (read/write beyond cylinder 203)
  // if found, truncate request length
  bool ovr = lba + nblk > unit.NBlock();
  if (ovr) nwrd = (unit.NBlock()-lba) * (unit.BlockSize()/2);
 
  // remember request parameters for call back
  fRd_rkcs  = rkcs;
  fRd_rkda  = rkda;
  fRd_addr  = addr;
  fRd_lba   = lba;
  fRd_nwrd  = nwrd;
  fRd_ovr   = ovr;
  fRd_fu    = fu;
 
  // now handle the functions
  if (fu == kFUNC_CRESET) {                 // Control reset -----------------
    fStats.Inc(kStatNFuncCreset);
    cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_CRESET);
 
  } else if (fu == kFUNC_WRITE) {           // Write -------------------------
                                            //   Note: WRITE+FMT is just WRITE
    fStats.Inc(kStatNFuncWrite);
    if (se >= unit.NSector())   rker |= kRKER_M_NXS;
    if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
    if (unit.WProt())           rker |= kRKER_M_WLO;
    if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE;  // IBA not supported
    if (rker) {
      AddErrorExit(clist, rker);
    } else {
      fRdma.QueueDiskWrite(addr, nwrd, 
                           Rw11Cpu::kCPAH_M_22BIT|Rw11Cpu::kCPAH_M_UBMAP,
                           lba, &unit);
    }
 
  } else if (fu == kFUNC_READ) {            // Read --------------------------
    fStats.Inc(kStatNFuncRead);
    if (se >= unit.NSector())   rker |= kRKER_M_NXS;
    if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
    if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE;  // IBA not supported
    if (rker) {
      AddErrorExit(clist, rker);
    } else {
      fRdma.QueueDiskRead(addr, nwrd, 
                          Rw11Cpu::kCPAH_M_22BIT|Rw11Cpu::kCPAH_M_UBMAP,
                          lba, &unit);
    }
 
  } else if (fu == kFUNC_WCHK) {            // Write Check -------------------
    fStats.Inc(kStatNFuncWchk);
    if (se >= unit.NSector())   rker |= kRKER_M_NXS;
    if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
    if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE;  // IBA not supported
    if (rker) {
      AddErrorExit(clist, rker);
    } else {
      fRdma.QueueDiskWriteCheck(addr, nwrd, 
                                Rw11Cpu::kCPAH_M_22BIT|Rw11Cpu::kCPAH_M_UBMAP,
                                lba, &unit);
    }
 
  } else if (fu == kFUNC_SEEK) {            // Seek --------------------------
    fStats.Inc(kStatNFuncSeek);
    if (se >= unit.NSector())   rker |= kRKER_M_NXS;
    if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
    if (rker) {
      cpu.AddWibr(clist, fBase+kRKER, rker);
      cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_SBCLR | (1u<<dr));
      cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
      LogRker(rker);
    } else {
      cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
      rkds &= ~kRKDS_B_SC;                  // replace current sector number
      rkds |= se;
      unit.SetRkds(rkds);
      cpu.AddWibr(clist, fBase+kRKDS, rkds);
      cpu.AddWibr(clist, fBase+kRKMR, 1u<<dr); // issue seek done
    }
 
  } else if (fu == kFUNC_RCHK) {            // Read Check --------------------
    fStats.Inc(kStatNFuncRchk);
    if (se >= unit.NSector())   rker |= kRKER_M_NXS;
    if (cy >= unit.NCylinder()) rker |= kRKER_M_NXC;
    if (rkcs & kRKCS_M_IBA) rker |= kRKER_M_DRE;  // IBA not supported
    if (rker) {
      AddErrorExit(clist, rker);
    } else {
      AddNormalExit(clist, nwrd, 0);        // no action, virt disks don't err
    }
 
  } else if (fu == kFUNC_DRESET) {          // Drive Reset -------------------
    fStats.Inc(kStatNFuncDreset);
    cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
    cpu.AddWibr(clist, fBase+kRKMR, 1u<<dr);   // issue seek done
 
  } else if (fu == kFUNC_WLOCK) {           // Write Lock --------------------
    fStats.Inc(kStatNFuncWlock);
    rkds |= kRKDS_M_WPS;                    // set RKDS write protect flag
    unit.SetRkds(rkds);
    unit.SetWProt(true);
    cpu.AddWibr(clist, fBase+kRKDS, rkds);
    cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
  }
 
  if (clist.Size()) {                       // if handled directly
    Server().Exec(clist);                   // doit
  }
  return 0;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlRK11::RdmaPreExecCB(int stat, size_t nwdone, size_t nwnext,
                                 RlinkCommandList& clist)
{
  // if last chunk and not doing WCHK add a labo and normal exit csr update
  if (stat == Rw11Rdma::kStatusBusyLast && fRd_fu != kFUNC_WCHK) {
    clist.AddLabo();
    AddNormalExit(clist, nwdone+nwnext, 0);
  }
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlRK11::RdmaPostExecCB(int stat, size_t ndone,
                                  RlinkCommandList& clist, size_t ncmd)
{
  if (stat == Rw11Rdma::kStatusBusy) return;
 
  uint16_t rker = 0;
 
  // handle write check
  if (fRd_fu == kFUNC_WCHK) {
    size_t nwcok = fRdma.WriteCheck(ndone);
    if (nwcok != ndone) {                   // if mismatch found
      rker |= kRKER_M_WCE;                  // set error flag
      if (fRd_rkcs & kRKCS_M_SSE) {         // if 'stop-on-soft' requested
        ndone = nwcok;                      // truncate word count
      }
    }
  }
 
  // handle Rdma aborts
  if (stat == Rw11Rdma::kStatusFailRdma) rker |= kRKER_M_NXM;
 
  // check for fused csr updates
  if (clist.Size() > ncmd) {
    uint8_t  ccode = clist[ncmd].Command();
    uint16_t cdata = clist[ncmd].Data();
    if (ccode != RlinkCommand::kCmdLabo || (rker != 0 && cdata == 0))
      throw Rexception("Rw11CntlRK11::RdmaPostExecCB",
                       "Bad state: Labo not found or missed abort");
    if (cdata == 0) return;
  }
 
  // finally to RK11 register update
  RlinkCommandList clist1;
  AddNormalExit(clist1, ndone, rker);
  Server().Exec(clist1);
 
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlRK11::LogRker(uint16_t rker)
{
  RlogMsg lmsg(LogFile());
  lmsg << "-E RK11 er=" << RosPrintBvi(rker,8) << "  ERROR ABORT";
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlRK11::AddErrorExit(RlinkCommandList& clist, uint16_t rker)
{
  Rw11Cpu& cpu = Cpu();
  cpu.AddWibr(clist, fBase+kRKER, rker);
  cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
  LogRker(rker);
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlRK11::AddNormalExit(RlinkCommandList& clist, size_t ndone,
                                 uint16_t rker)
{
  Rw11Cpu& cpu  = Cpu();
  uint16_t dr   = (fRd_rkda>>kRKDA_V_DRSEL) & kRKDA_B_DRSEL;
  Rw11UnitRK11& unit = *fspUnit[dr];
 
  size_t nblk   = unit.Nwrd2Nblk(ndone);
 
  uint32_t addr = fRd_addr + 2*ndone;
  size_t   lba  = fRd_lba  + nblk;
  uint32_t nrest = fRd_nwrd - ndone;
 
  uint16_t ba   = addr & 0177776;           // get lower 16 bits
  uint16_t mex  = (addr>>16) & 03;          // get upper  2 bits
  uint16_t cs   = (fRd_rkcs & ~kRKCS_M_MEX) | (mex << kRKCS_V_MEX);
  uint16_t se;
  uint16_t hd;
  uint16_t cy;
  unit.Lba2Chs(lba, cy,hd,se);
  uint16_t da   = (fRd_rkda & kRKDA_M_DRSEL) | (cy<<kRKDA_V_CYL) |
                  (hd<<kRKDA_V_SUR) | se;
 
  if (fRd_ovr) rker |= kRKER_M_OVR;
 
  if (rker) {
    cpu.AddWibr(clist, fBase+kRKER, rker);
    LogRker(rker);
  }
  cpu.AddWibr(clist, fBase+kRKWC, uint16_t((-nrest)&0177777));
  cpu.AddWibr(clist, fBase+kRKBA, ba);
  cpu.AddWibr(clist, fBase+kRKDA, da);
  if (cs != fRd_rkcs) 
    cpu.AddWibr(clist, fBase+kRKCS, cs);
  cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
 
  return;
}
 
 
} // end namespace Retro
 

Go to most recent revision | 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.