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

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.74/] [tools/] [src/] [librw11/] [Rw11CntlRHRP.cpp] - Rev 30

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

// $Id: Rw11CntlRHRP.cpp 680 2015-05-14 13:29:46Z 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-05-14   680   1.0    Initial version
// 2015-03-21   659   0.1    First draft
// ---------------------------------------------------------------------------
 
/*!
  \file
  \version $Id: Rw11CntlRHRP.cpp 680 2015-05-14 13:29:46Z mueller $
  \brief   Implemenation of Rw11CntlRHRP.
*/
 
#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 "Rw11CntlRHRP.hpp"
 
using namespace std;
 
/*!
  \class Retro::Rw11CntlRHRP
  \brief FIXME_docs
*/
 
// all method definitions in namespace Retro
namespace Retro {
 
//------------------------------------------+-----------------------------------
// constants definitions
 
const uint16_t Rw11CntlRHRP::kIbaddr;
const int      Rw11CntlRHRP::kLam;
 
const uint16_t Rw11CntlRHRP::kRPCS1;
const uint16_t Rw11CntlRHRP::kRPWC;
const uint16_t Rw11CntlRHRP::kRPBA;
const uint16_t Rw11CntlRHRP::kRPDA;
const uint16_t Rw11CntlRHRP::kRPCS2;
const uint16_t Rw11CntlRHRP::kRPDS;
const uint16_t Rw11CntlRHRP::kRPER1;
const uint16_t Rw11CntlRHRP::kRPAS;
const uint16_t Rw11CntlRHRP::kRPLA;
const uint16_t Rw11CntlRHRP::kRPDB;
const uint16_t Rw11CntlRHRP::kRPMR1;
const uint16_t Rw11CntlRHRP::kRPDT;
const uint16_t Rw11CntlRHRP::kRPSN;
const uint16_t Rw11CntlRHRP::kRPOF;
const uint16_t Rw11CntlRHRP::kRPDC;
const uint16_t Rw11CntlRHRP::kRxM13;
const uint16_t Rw11CntlRHRP::kRxM14;
const uint16_t Rw11CntlRHRP::kRxM15;
const uint16_t Rw11CntlRHRP::kRPEC1;
const uint16_t Rw11CntlRHRP::kRPEC2;
const uint16_t Rw11CntlRHRP::kRPBAE;
const uint16_t Rw11CntlRHRP::kRPCS3;
 
const uint16_t Rw11CntlRHRP::kProbeOff;
const bool     Rw11CntlRHRP::kProbeInt;
const bool     Rw11CntlRHRP::kProbeRem;
 
const uint16_t Rw11CntlRHRP::kRPCS1_M_SC;
const uint16_t Rw11CntlRHRP::kRPCS1_M_TRE;
const uint16_t Rw11CntlRHRP::kRPCS1_M_DVA;
const uint16_t Rw11CntlRHRP::kRPCS1_M_BAE;
const uint16_t Rw11CntlRHRP::kRPCS1_V_BAE;
const uint16_t Rw11CntlRHRP::kRPCS1_B_BAE;
const uint16_t Rw11CntlRHRP::kRPCS1_M_RDY;
const uint16_t Rw11CntlRHRP::kRPCS1_M_IE;
const uint16_t Rw11CntlRHRP::kRPCS1_V_FUNC;
const uint16_t Rw11CntlRHRP::kRPCS1_B_FUNC;
const uint16_t Rw11CntlRHRP::kRPCS1_M_GO;
 
const uint16_t Rw11CntlRHRP::kFUNC_WCD;
const uint16_t Rw11CntlRHRP::kFUNC_WCHD;
const uint16_t Rw11CntlRHRP::kFUNC_WRITE;
const uint16_t Rw11CntlRHRP::kFUNC_WHD;
const uint16_t Rw11CntlRHRP::kFUNC_READ;
const uint16_t Rw11CntlRHRP::kFUNC_RHD;
 
const uint16_t Rw11CntlRHRP::kRFUNC_WUNIT;
const uint16_t Rw11CntlRHRP::kRFUNC_CUNIT;
const uint16_t Rw11CntlRHRP::kRFUNC_DONE;
const uint16_t Rw11CntlRHRP::kRFUNC_WIDLY;
 
const uint16_t Rw11CntlRHRP::kRPCS1_V_RUNIT;
const uint16_t Rw11CntlRHRP::kRPCS1_B_RUNIT;
const uint16_t Rw11CntlRHRP::kRPCS1_M_RATA;
const uint16_t Rw11CntlRHRP::kRPCS1_V_RIDLY;
const uint16_t Rw11CntlRHRP::kRPCS1_B_RIDLY;
 
const uint16_t Rw11CntlRHRP::kRPDA_V_TA;
const uint16_t Rw11CntlRHRP::kRPDA_B_TA;
const uint16_t Rw11CntlRHRP::kRPDA_B_SA;
 
const uint16_t Rw11CntlRHRP::kRPCS2_M_RWCO;
const uint16_t Rw11CntlRHRP::kRPCS2_M_WCE;
const uint16_t Rw11CntlRHRP::kRPCS2_M_NED;
const uint16_t Rw11CntlRHRP::kRPCS2_M_NEM;
const uint16_t Rw11CntlRHRP::kRPCS2_M_PGE;
const uint16_t Rw11CntlRHRP::kRPCS2_M_MXF;
const uint16_t Rw11CntlRHRP::kRPCS2_M_OR;
const uint16_t Rw11CntlRHRP::kRPCS2_M_IR;
const uint16_t Rw11CntlRHRP::kRPCS2_M_CLR;
const uint16_t Rw11CntlRHRP::kRPCS2_M_PAT;
const uint16_t Rw11CntlRHRP::kRPCS2_M_BAI;
const uint16_t Rw11CntlRHRP::kRPCS2_M_UNIT2;
const uint16_t Rw11CntlRHRP::kRPCS2_B_UNIT;
 
const uint16_t Rw11CntlRHRP::kRPDS_M_ATA;
const uint16_t Rw11CntlRHRP::kRPDS_M_ERP;
const uint16_t Rw11CntlRHRP::kRPDS_M_MOL;
const uint16_t Rw11CntlRHRP::kRPDS_M_WRL;
const uint16_t Rw11CntlRHRP::kRPDS_M_LBT;
const uint16_t Rw11CntlRHRP::kRPDS_M_DPR;
const uint16_t Rw11CntlRHRP::kRPDS_M_DRY;
const uint16_t Rw11CntlRHRP::kRPDS_M_VV;
const uint16_t Rw11CntlRHRP::kRPDS_M_OM ;
 
const uint16_t Rw11CntlRHRP::kRPER1_M_UNS;
const uint16_t Rw11CntlRHRP::kRPER1_M_WLE;
const uint16_t Rw11CntlRHRP::kRPER1_M_IAE;
const uint16_t Rw11CntlRHRP::kRPER1_M_AOE;
const uint16_t Rw11CntlRHRP::kRPER1_M_RMR;
const uint16_t Rw11CntlRHRP::kRPER1_M_ILF;
 
const uint16_t Rw11CntlRHRP::kRPDC_B_CA;
 
const uint16_t Rw11CntlRHRP::kRPCS3_M_IE;
const uint16_t Rw11CntlRHRP::kRPCS3_M_RSEARDONE;
const uint16_t Rw11CntlRHRP::kRPCS3_M_RPACKDONE;
const uint16_t Rw11CntlRHRP::kRPCS3_M_RPOREDONE;
const uint16_t Rw11CntlRHRP::kRPCS3_M_RSEEKDONE;
 
//------------------------------------------+-----------------------------------
//! Default constructor
 
Rw11CntlRHRP::Rw11CntlRHRP()
  : Rw11CntlBase<Rw11UnitRHRP,4>("rhrp"),
    fPC_rpcs1(0),
    fPC_rpcs2(0),
    fPC_rpcs3(0),
    fPC_rpwc(0),
    fPC_rpba(0),
    fPC_rpbae(0),
    fPC_cunit(0),
    fPC_rpds(0),
    fPC_rpda(0),
    fPC_rpdc(0),
    fRd_rpcs1(0),
    fRd_rpcs2(0),
    fRd_rpcs3(0),
    fRd_rpwc(0),
    fRd_rpba(0),
    fRd_rpbae(0),
    fRd_rpds(0),
    fRd_rpda(0),
    fRd_rpdc(0),
    fRd_addr(0),
    fRd_lba(0),
    fRd_nwrd(0),
    fRd_fu(0),
    fRd_ovr(false),
    fRdma(this,
          boost::bind(&Rw11CntlRHRP::RdmaPreExecCB,  this, _1, _2, _3, _4),
          boost::bind(&Rw11CntlRHRP::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 Rw11UnitRHRP(this, i));
  }
 
  fStats.Define(kStatNFuncWchk   , "NFuncWchk"    , "func WCHK");
  fStats.Define(kStatNFuncWrite  , "NFuncWrite"   , "func WRITE");
  fStats.Define(kStatNFuncRead   , "NFuncRead"    , "func READ");
  fStats.Define(kStatNFuncSear   , "NFuncSear"    , "func SEARCH (loc)");
  fStats.Define(kStatNFuncPack   , "NFuncPack"    , "func PACK ACK (loc)");
  fStats.Define(kStatNFuncPore   , "NFuncPore"    , "func PORT REL (loc)");
  fStats.Define(kStatNFuncSeek   , "NFuncSeek"    , "func SEEK (loc)");
}
 
//------------------------------------------+-----------------------------------
//! Destructor
 
Rw11CntlRHRP::~Rw11CntlRHRP()
{}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlRHRP::Config(const std::string& name, uint16_t base, int lam)
{
  ConfigCntl(name, base, lam, kProbeOff, kProbeInt, kProbeRem);
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlRHRP::Start()
{
  if (fStarted || fLam<0 || !fEnable || !fProbe.Found())
    throw Rexception("Rw11CntlRHRP::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()+".cs1", Base() + kRPCS1);
  Cpu().AllIAddrMapInsert(Name()+".wc",  Base() + kRPWC);
  Cpu().AllIAddrMapInsert(Name()+".ba",  Base() + kRPBA);
  Cpu().AllIAddrMapInsert(Name()+".da",  Base() + kRPDA);
  Cpu().AllIAddrMapInsert(Name()+".cs2", Base() + kRPCS2);
  Cpu().AllIAddrMapInsert(Name()+".ds",  Base() + kRPDS);
  Cpu().AllIAddrMapInsert(Name()+".er1", Base() + kRPER1);
  Cpu().AllIAddrMapInsert(Name()+".as",  Base() + kRPAS);
  Cpu().AllIAddrMapInsert(Name()+".la",  Base() + kRPLA);
  Cpu().AllIAddrMapInsert(Name()+".db",  Base() + kRPDB);
  Cpu().AllIAddrMapInsert(Name()+".mr1", Base() + kRPMR1);
  Cpu().AllIAddrMapInsert(Name()+".dt",  Base() + kRPDT);
  Cpu().AllIAddrMapInsert(Name()+".sn",  Base() + kRPSN);
  Cpu().AllIAddrMapInsert(Name()+".of",  Base() + kRPOF);
  Cpu().AllIAddrMapInsert(Name()+".dc",  Base() + kRPDC);
  Cpu().AllIAddrMapInsert(Name()+".m13", Base() + kRxM13);
  Cpu().AllIAddrMapInsert(Name()+".m14", Base() + kRxM14);
  Cpu().AllIAddrMapInsert(Name()+".m15", Base() + kRxM15);
  Cpu().AllIAddrMapInsert(Name()+".ec1", Base() + kRPEC1);
  Cpu().AllIAddrMapInsert(Name()+".ec2", Base() + kRPEC2);
  Cpu().AllIAddrMapInsert(Name()+".bae", Base() + kRPBAE);
  Cpu().AllIAddrMapInsert(Name()+".cs3", Base() + kRPCS3);
 
  // setup primary info clist
  fPrimClist.Clear();
  fPrimClist.AddAttn();
  fPC_rpcs1 = Cpu().AddRibr(fPrimClist, fBase+kRPCS1);
  fPC_rpcs2 = Cpu().AddRibr(fPrimClist, fBase+kRPCS2);
  fPC_rpcs3 = Cpu().AddRibr(fPrimClist, fBase+kRPCS3);
  fPC_rpwc  = Cpu().AddRibr(fPrimClist, fBase+kRPWC);
  fPC_rpba  = Cpu().AddRibr(fPrimClist, fBase+kRPBA);
  fPC_rpbae = Cpu().AddRibr(fPrimClist, fBase+kRPBAE);
 
  fPC_cunit = Cpu().AddWibr(fPrimClist, fBase+kRPCS1,
                            (kRFUNC_CUNIT << kRPCS1_V_FUNC) );
 
  fPC_rpds  = Cpu().AddRibr(fPrimClist, fBase+kRPDS);
  fPC_rpda  = Cpu().AddRibr(fPrimClist, fBase+kRPDA);
  fPC_rpdc  = Cpu().AddRibr(fPrimClist, fBase+kRPDC);
 
  // add attn handler
  Server().AddAttnHandler(boost::bind(&Rw11CntlRHRP::AttnHandler, this, _1), 
                          uint16_t(1)<<fLam, (void*)this);
 
  fStarted = true;
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlRHRP::UnitSetup(size_t ind)
{
  Rw11UnitRHRP& unit = *fspUnit[ind];
  RlinkCommandList clist;
  Rw11Cpu& cpu  = Cpu();
 
  // only two mayor drive states are used
  //  power medium  wlock : ds flags
  //   off    ---     --- : dpr=0  mol=0  wrl=0  (disabled, type=off)
  //    on    off     --- : dpr=1  mol=0  wrl=0  (enabled, no file attached)
  //    on     on      no : dpr=1  mol=1  wrl=0  (file attached)
  //    on     on     yes : dpr=1  mol=1  wrl=1  (file attached + wlock)
 
  uint16_t rpds = 0;
 
  if (unit.Type() != "off") {               // is enabled
    rpds |= kRPDS_M_DPR;
    if (unit.Virt()) {                        // file attached
      rpds |= kRPDS_M_MOL;                    // -> set MOL
      rpds |= kRPDS_M_ERP;                    // -> clear ER1 via ERP=1
      if (unit.WProt()) rpds |= kRPDS_M_WRL; // in case write protected
    }
    if ((unit.Rpds() ^ rpds) & kRPDS_M_MOL) { // mol state change ?
      rpds |= kRPDS_M_ATA;                      // cause attentions
      rpds |= kRPDS_M_VV;                       // reset volume valid
    }
  }
 
  unit.SetRpds(rpds);                       // remember new DS
  cpu.AddWibr(clist, fBase+kRPCS1,          // setup unit
              (ind << kRPCS1_V_RUNIT) | 
              (kRFUNC_WUNIT << kRPCS1_V_FUNC) );
  cpu.AddWibr(clist, fBase+kRPDT, unit.Rpdt()); // setup DT
  cpu.AddWibr(clist, fBase+kRPDS, rpds);        // setup DS
  Server().Exec(clist);
 
  return;
}  
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
bool Rw11CntlRHRP::BootCode(size_t unit, std::vector<uint16_t>& code, 
                            uint16_t& aload, uint16_t& astart)
{
  uint16_t kBOOT_START = 02000;
  uint16_t bootcode[] = {      // rh/rp boot loader - from simh pdp11_rp.c (v3.9)
    0042102,                   // "BD"
    0012706, kBOOT_START,      // mov #boot_start, sp
    0012700, uint16_t(unit),   // mov #unit, r0
    0012701, 0176700,          // mov #RPCS1, r1
    0012761, 0000040, 0000010, // mov #CS2_CLR, 10(r1) ; reset
    0010061, 0000010,          // mov r0, 10(r1)       ; set unit
    0012711, 0000021,          // mov #RIP+GO, (r1)    ; pack ack
    0012761, 0010000, 0000032, // mov #FMT16B, 32(r1)  ; 16b mode
    0012761, 0177000, 0000002, // mov #-512., 2(r1)    ; set wc
    0005061, 0000004,          // clr 4(r1)            ; clr ba
    0005061, 0000006,          // clr 6(r1)            ; clr da
    0005061, 0000034,          // clr 34(r1)           ; clr cyl
    0012711, 0000071,          // mov #READ+GO, (r1)   ; read 
    0105711,                   // tstb (r1)            ; wait
    0100376,                   // bpl .-2
    0005002,                   // clr R2
    0005003,                   // clr R3
    0012704, uint16_t(kBOOT_START+020), // mov #start+020, r4
    0005005,                   // clr R5
    0105011,                   // clrb (r1)
    0005007                    // clr PC
    };
 
  code.clear();
  foreach_ (uint16_t& w, bootcode) code.push_back(w); 
  aload  = kBOOT_START;
  astart = kBOOT_START+2;
  return true;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlRHRP::Dump(std::ostream& os, int ind, const char* text) const
{
  RosFill bl(ind);
  os << bl << (text?text:"--") << "Rw11CntlRHRP @ " << this << endl;
  os << bl << "  fPC_rpcs1:       " << RosPrintf(fPC_rpcs1,"d",6) << endl;
  os << bl << "  fPC_rpcs2:       " << RosPrintf(fPC_rpcs2,"d",6) << endl;
  os << bl << "  fPC_rpcs3:       " << RosPrintf(fPC_rpcs3,"d",6) << endl;
  os << bl << "  fPC_rpwc:        " << RosPrintf(fPC_rpwc,"d",6) << endl;
  os << bl << "  fPC_rpba:        " << RosPrintf(fPC_rpba,"d",6) << endl;
  os << bl << "  fPC_rpbae:       " << RosPrintf(fPC_rpbae,"d",6) << endl;
  os << bl << "  fPC_cunit:       " << RosPrintf(fPC_cunit,"d",6) << endl;
  os << bl << "  fPC_rpds:        " << RosPrintf(fPC_rpds,"d",6) << endl;
  os << bl << "  fPC_rpda:        " << RosPrintf(fPC_rpda,"d",6) << endl;
  os << bl << "  fPC_rpdc:        " << RosPrintf(fPC_rpdc,"d",6) << endl;
  os << bl << "  fRd_rpcs1:       " << RosPrintBvi(fRd_rpcs1) << endl;
  os << bl << "  fRd_rpcs2:       " << RosPrintBvi(fRd_rpcs2) << endl;
  os << bl << "  fRd_rpcs3:       " << RosPrintBvi(fRd_rpcs3) << endl;
  os << bl << "  fRd_rpwc:        " << RosPrintBvi(fRd_rpwc) << endl;
  os << bl << "  fRd_rpba:        " << RosPrintBvi(fRd_rpba) << endl;
  os << bl << "  fRd_rpbae:       " << RosPrintBvi(fRd_rpbae) << endl;
  os << bl << "  fRd_rpds:        " << RosPrintBvi(fRd_rpds) << endl;
  os << bl << "  fRd_rpda:        " << RosPrintBvi(fRd_rpda) << endl;
  os << bl << "  fRd_rpdc:        " << RosPrintBvi(fRd_rpdc) << endl;
  os << bl << "  fRd_addr:        " << RosPrintBvi(fRd_addr,8,22) << endl;
  os << bl << "  fRd_lba:         " << RosPrintf(fRd_lba,"d",6)  << endl;
  os << bl << "  fRd_nwrd:        " << RosPrintf(fRd_nwrd,"d",6) << endl;
  os << bl << "  fRd_fu:          " << RosPrintf(fRd_fu,"d",6) << endl;
  os << bl << "  fRd_ovr:         " << fRd_ovr  << endl;
  fRdma.Dump(os, ind+2, "fRdma: ");
  Rw11CntlBase<Rw11UnitRHRP,4>::Dump(os, ind, " ^");
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int Rw11CntlRHRP::AttnHandler(RlinkServer::AttnArgs& args)
{
  fStats.Inc(kStatNAttnHdl);
  Server().GetAttnInfo(args, fPrimClist);
 
  uint16_t rpcs1 = fPrimClist[fPC_rpcs1].Data();
  uint16_t rpcs2 = fPrimClist[fPC_rpcs2].Data();
  uint16_t rpcs3 = fPrimClist[fPC_rpcs3].Data();
  uint16_t rpwc  = fPrimClist[fPC_rpwc ].Data();
  uint16_t rpba  = fPrimClist[fPC_rpba ].Data();
  uint16_t rpbae = fPrimClist[fPC_rpbae].Data();
  uint16_t rpds  = fPrimClist[fPC_rpds ].Data();
  uint16_t rpda  = fPrimClist[fPC_rpda ].Data();
  uint16_t rpdc  = fPrimClist[fPC_rpdc ].Data();
 
  uint16_t unum  = rpcs2 & kRPCS2_B_UNIT;
  uint16_t fu    = (rpcs1>>kRPCS1_V_FUNC)  & kRPCS1_B_FUNC;
 
  uint32_t addr = uint32_t(rpbae)<<16 | uint32_t(rpba);
 
  uint16_t sa   =  rpda              & kRPDA_B_SA;
  uint16_t ta   = (rpda>>kRPDA_V_TA) & kRPDA_B_TA;
  uint16_t ca   =  rpdc              & kRPDC_B_CA;
 
  uint32_t nwrd = (~uint32_t(rpwc)&0xffff) + 1; // transfer size in words
 
  // all 4 units are always available, but check anyway
  if (unum > NUnit())
    throw Rexception("Rw11CntlRHRP::AttnHandler","Bad state: unum > NUnit()");
 
  Rw11UnitRHRP& unit = *fspUnit[unum];
  //Rw11Cpu& cpu = Cpu();
  RlinkCommandList clist;
 
  uint32_t lba  = unit.Chs2Lba(ca,ta,sa);
  uint32_t nblk = unit.Nwrd2Nblk(nwrd);
 
  if (fTraceLevel>0) {
    RlogMsg lmsg(LogFile());
    static const char* fumnemo[32] = 
      {"00 ","01 ","02 ","03 ","04 ","05 ","06 ","07 ",    // 00---
       "10 ","11 ","12 ","13 ","14 ","15 ","16 ","17 ",    // 01---
       "20 ","21 ","22 ","23 ","wc ","wch","26 ","27 ",    // 10---
       "wr ","wrh","32 ","33 ","rd ","rdh","36 ","37 "};   // 11---
    lmsg << "-I RHRP"
         << " fu=" << fumnemo[fu&037]
         << " cs=" << RosPrintBvi(rpcs1,8)
         << "," << RosPrintBvi(rpcs2,8)
         << " ad=" << RosPrintBvi(addr,8,22)
         << " pa=" << unum
         << "," << RosPrintf(ca,"d",3) 
         << "," << RosPrintf(ta,"d",2)
         << "," << RosPrintf(sa,"d",2)
         << " la,nw=" << RosPrintf(lba,"d",6) 
         << ",";
    if (nwrd==65536) lmsg << "  (0)"; else lmsg << RosPrintf(nwrd,"d",5);
  }
 
  // handle cs3 done flags, just count them
  if (rpcs3 & kRPCS3_M_RSEARDONE) fStats.Inc(kStatNFuncSear);
  if (rpcs3 & kRPCS3_M_RPOREDONE) fStats.Inc(kStatNFuncPore);
  if (rpcs3 & kRPCS3_M_RPACKDONE) fStats.Inc(kStatNFuncPack);
  if (rpcs3 & kRPCS3_M_RSEEKDONE) fStats.Inc(kStatNFuncSeek);
 
  // check for overrun (read/write beyond last track
  // 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 and error exit handling
 
  fRd_rpcs1 = rpcs1;
  fRd_rpcs2 = rpcs2;
  fRd_rpcs3 = rpcs3;
  fRd_rpwc  = rpwc;
  fRd_rpba  = rpba;
  fRd_rpbae = rpbae;
  fRd_rpds  = rpds;
  fRd_rpda  = rpda;
  fRd_rpdc  = rpdc;
  fRd_addr  = addr;
  fRd_lba   = lba;
  fRd_nwrd  = nwrd;
  fRd_fu    = fu;
  fRd_ovr   = ovr;
 
  // check for general abort conditions
  // note: only 'data transfer' functions handled via backend
  //       SEEK and others are done in ibdr_rhrp autonomously
 
  // not attached --> signal drive unsave status
  if (! unit.Virt()) {                      // not attached
    AddErrorExit(clist, kRPER1_M_UNS);      // signal UNS (drive unsafe)
    Server().Exec(clist);                   // doit
    return 0;
  }
 
  // invalid disk address
  if (ca > unit.NCylinder() || ta > unit.NHead() || sa > unit.NSector()) {
    AddErrorExit(clist, kRPER1_M_IAE);      // signal IAE (invalid address err)
    Server().Exec(clist);                   // doit
    return 0;
  }
 
  // now handle the functions
  if (fu == kFUNC_WRITE) {                  // Write -------------------------
    fStats.Inc(kStatNFuncWrite);
    if (unit.WProt()) {                     // write on write locked drive ?
      AddErrorExit(clist, kRPER1_M_WLE);    // signal WLE (write lock error)
    } else {
      fRdma.QueueDiskWrite(addr, nwrd, Rw11Cpu::kCPAH_M_22BIT, lba, &unit);
    }
 
  } else if (fu == kFUNC_WCD) {             // Write Check -------------------
    fStats.Inc(kStatNFuncWchk );
    fRdma.QueueDiskWriteCheck(addr, nwrd, Rw11Cpu::kCPAH_M_22BIT, lba, &unit);
 
  } else if (fu == kFUNC_READ ) {           // Read --------------------------
    fStats.Inc(kStatNFuncRead);
    fRdma.QueueDiskRead(addr, nwrd, Rw11Cpu::kCPAH_M_22BIT, lba, &unit);
 
  } else {
    // FIXME: handle other special functions (currently simply error out !!)
    AddErrorExit(clist, kRPER1_M_ILF);      // signal ILF (invalid function)
    Server().Exec(clist);                   // doit
    return 0;
  }
 
  if (clist.Size()) {                       // if handled directly
    Server().Exec(clist);                   // doit
  }
 
  return 0;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlRHRP::RdmaPreExecCB(int stat, size_t nwdone, size_t nwnext,
                                 RlinkCommandList& clist)
{
  // if last chunk and not doing WCD add a labo and normal exit csr update
  if (stat == Rw11Rdma::kStatusBusyLast && fRd_fu != kFUNC_WCD) {
    clist.AddLabo();
    AddNormalExit(clist, nwdone+nwnext, 0, 0);
  }
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlRHRP::RdmaPostExecCB(int stat, size_t ndone,
                                  RlinkCommandList& clist, size_t ncmd)
{
  if (stat == Rw11Rdma::kStatusBusy) return;
 
  uint16_t rper1 = 0;
  uint16_t rpcs2 = 0;
 
  if (fRd_fu == kFUNC_WCD) {
    size_t nwcok = fRdma.WriteCheck(ndone);
    if (nwcok != ndone) {                   // if mismatch found
      rpcs2 = kRPCS2_M_WCE;
      if (ndone & 0x1) rpcs2 = kRPCS2_M_RWCO; // failed in odd word !
      ndone = nwcok;                        // truncate word count
    }
  }
 
  // handle Rdma aborts
  if (stat == Rw11Rdma::kStatusFailRdma) rpcs2 = kRPCS2_M_NEM;
 
  // 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 || (rper1 != 0 && cdata == 0))
      throw Rexception("Rw11CntlRHRP::RdmaPostExecCB",
                       "Bad state: Labo not found or missed abort");
    if (cdata == 0) return;
  }
 
  // finally to RHRP register update
  RlinkCommandList clist1;
  AddNormalExit(clist1, ndone, rper1, rpcs2);
  Server().Exec(clist1);
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlRHRP::AddErrorExit(RlinkCommandList& clist, uint16_t rper1)
{
  Rw11Cpu& cpu  = Cpu();
 
  cpu.AddWibr(clist, fBase+kRPCS1, (kRFUNC_CUNIT<<kRPCS1_V_FUNC) );
  cpu.AddWibr(clist, fBase+kRPER1, rper1);
 
  // use ATA termination ! Comes late, but should be ok
  cpu.AddWibr(clist, fBase+kRPCS1, kRPCS1_M_RATA|(kRFUNC_DONE<<kRPCS1_V_FUNC) );
 
  if (fTraceLevel>1) {
    RlogMsg lmsg(LogFile());
    lmsg << "-I RHRP"
         << "   err "
         << " cs1=" << RosPrintBvi(fRd_rpcs1,8)
         << " er1=" << RosPrintBvi(rper1,2,16);
  }
 
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlRHRP::AddNormalExit(RlinkCommandList& clist, size_t ndone,
                                 uint16_t rper1, uint16_t rpcs2)
{
  Rw11Cpu& cpu  = Cpu();
  uint16_t unum  = fRd_rpcs2 & kRPCS2_B_UNIT;
  Rw11UnitRHRP& unit = *fspUnit[unum];
 
  size_t nblk    = unit.Nwrd2Nblk(ndone);
  uint32_t addr  = fRd_addr + 2*ndone;
  size_t   lba   = fRd_lba  + nblk;
 
  uint16_t ba   = addr & 0177776;           // get lower 16 bits
  uint16_t bae  = (addr>>16) & 077;         // get upper  6 bits
 
  uint16_t sa;
  uint16_t ta;
  uint16_t ca;
  unit.Lba2Chs(lba, ca,ta,sa);
  uint16_t da   = (ta<<kRPDA_V_TA) | sa;
  uint16_t wc   = fRd_rpwc + uint16_t(ndone);
 
  if (fRd_ovr) rper1 |= kRPER1_M_AOE;
 
  cpu.AddWibr(clist, fBase+kRPWC,  wc);
  cpu.AddWibr(clist, fBase+kRPBA,  ba);
  cpu.AddWibr(clist, fBase+kRPBAE, bae);
 
  cpu.AddWibr(clist, fBase+kRPCS1, (kRFUNC_CUNIT<<kRPCS1_V_FUNC) );
  cpu.AddWibr(clist, fBase+kRPDA,  da);
  cpu.AddWibr(clist, fBase+kRPDC,  ca);
 
  if (rper1)  cpu.AddWibr(clist, fBase+kRPER1, rper1);
  if (rpcs2)  cpu.AddWibr(clist, fBase+kRPER1, rpcs2);
 
  cpu.AddWibr(clist, fBase+kRPCS1, (kRFUNC_DONE<<kRPCS1_V_FUNC) );
 
  if (fTraceLevel>1) {
    RlogMsg lmsg(LogFile());
    if (rper1 || rpcs2) {
      lmsg << "-I RHRP"
           << "   err "
           << " er1=" << RosPrintBvi(rper1,2,16)
           << " cs2=" << RosPrintBvi(rpcs2,2,8)
           << endl;
    }
    lmsg << "-I RHRP"
         << (rper1==0 ? "    ok " :"   err ")
         << " we=" << RosPrintBvi(wc,8) << "," << RosPrintBvi(rper1,8)
         << " ad=" << RosPrintBvi(addr,8,22)
         << " pa=" << unum
         << "," << RosPrintf(ca,"d",3)
         << "," << RosPrintf(ta,"d",2)
         << "," << RosPrintf(sa,"d",2)
         << " ca,da=" << RosPrintBvi(ca,8,10) << "," << RosPrintBvi(da,8);
  }
 
  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.