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

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.61/] [tools/] [src/] [librw11/] [Rw11CntlRK11.cpp] - Rev 21

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

// $Id: Rw11CntlRK11.cpp 515 2013-05-04 17:28:59Z mueller $
//
// Copyright 2013- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
// Other credits: 
//   the boot code 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
// 2013-04-20   508   1.0    Initial version
// 2013-02-10   485   0.1    First draft
// ---------------------------------------------------------------------------
 
/*!
  \file
  \version $Id: Rw11CntlRK11.cpp 515 2013-05-04 17:28:59Z 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_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_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::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_busy(false),
    fRd_rkcs(0),
    fRd_rkda(0),
    fRd_addr(0),
    fRd_lba(0),
    fRd_nwrd(0),
    fRd_ovr(false)
{
  // must here because Unit have a back-pointer (not available at Rw11CntlBase)
  for (size_t i=0; i<NUnit(); i++) {
    fspUnit[i].reset(new Rw11UnitRK11(this, i));
  }
}
 
//------------------------------------------+-----------------------------------
//! 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("Rw11CntlDL11::Start",
                     "Bad state: started, no lam, not enable, not found");
 
  // setup primary info clist
  fPrimClist.Clear();
  Cpu().AddIbrb(fPrimClist, fBase);
  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.AddIbrb(clist, fBase);
  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[] = {      // rk05 boot loader - from simh pdp11_rk.c 
    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
    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_busy:        " << fRd_busy << 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_ovr:         " << fRd_ovr  << endl;
 
  Rw11CntlBase<Rw11UnitRK11,8>::Dump(os, ind, " ^");
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int Rw11CntlRK11::AttnHandler(const RlinkServer::AttnArgs& args)
{
  RlinkCommandList* pclist;
  size_t off;
 
  GetPrimInfo(args, pclist, off);  
 
  uint16_t rkwc = (*pclist)[off+fPC_rkwc].Data();
  uint16_t rkba = (*pclist)[off+fPC_rkba].Data();
  uint16_t rkda = (*pclist)[off+fPC_rkda].Data();
  //uint16_t rkmr = (*pclist)[off+fPC_rkmr].Data();
  uint16_t rkcs = (*pclist)[off+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 = (2*nwrd+unit.BlockSize()-1)/unit.BlockSize();
 
  uint16_t rker = 0;
  uint16_t rkds = unit.Rkds();
 
  if (fTraceLevel>0) {
    RlogMsg lmsg(LogFile());
    lmsg << "-I RK11 cs=" << RosPrintBvi(rkcs,8)
         << " da=" << RosPrintBvi(rkda,8)
         << " ad=" << RosPrintBvi(addr,8,18)
         << " fu=" << fu
         << " dchs=" << dr 
         << "," << RosPrintf(cy,"d",3) 
         << "," << hd 
         << "," << RosPrintf(se,"d",2)
         << " lba,nw=" << RosPrintf(lba,"d",4) 
         << "," << RosPrintf(nwrd,"d",5);
  }
 
  // check for general abort conditions
  if (fu != kRKCS_CRESET &&                 // function not control reset
      (!unit.Virt())) {                     //   and drive not attached
    rker = kRKER_M_NXD;                     //   --> abort with NXD error
 
  } else if (fu != kRKCS_WRITE &&           // function neither write
             fu != kRKCS_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 == kRKCS_SEEK || fu == kRKCS_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);
  bool queue = false;
 
  // now handle the functions
  if (fu == kRKCS_CRESET) {                 // Control reset -----------------
    cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_CRESET);
    fRd_busy  = false;
 
  } else if (fu == kRKCS_WRITE) {           // Write -------------------------
                                            //   Note: WRITE+FMT is just WRITE
    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;  // not yet supported FIXME
    queue = true;
 
  } else if (fu == kRKCS_READ) {            // Read --------------------------
    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;  // not yet supported FIXME
    queue = true;
 
  } else if (fu == kRKCS_WCHK) {            // Write Check -------------------
    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;  // not yet supported FIXME
    queue = true;
 
  } else if (fu == kRKCS_SEEK) {            // Seek --------------------------
    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 == kRKCS_RCHK) {            // Read Check --------------------
    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;  // not yet supported FIXME
    queue = true;
 
  } else if (fu == kRKCS_DRESET) {          // Drive Reset -------------------
    cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
    cpu.AddWibr(clist, fBase+kRKMR, 1u<<dr);   // issue seek done
 
  } else if (fu == kRKCS_WLOCK) {           // Write Lock --------------------
    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 (queue) {                             // to be handled in RdmaHandlder
    if (rker) {                              // abort on case of errors
      cpu.AddWibr(clist, fBase+kRKER, rker);
      cpu.AddWibr(clist, fBase+kRKMR, kRKMR_M_FDONE);
      LogRker(rker);
    } else {                                 // or queue action 
      fRd_busy  = true;
      fRd_rkcs  = rkcs;
      fRd_rkda  = rkda;
      fRd_addr  = addr;
      fRd_lba   = lba;
      fRd_nwrd  = nwrd;
      fRd_ovr   = ovr;
      Server().QueueAction(boost::bind(&Rw11CntlRK11::RdmaHandler, this));
    }
 
  } else {                                  // handled here
    Server().Exec(clist);
  }
 
  return 0;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int Rw11CntlRK11::RdmaHandler()
{
  uint16_t rker = 0;
  uint16_t fu   = (fRd_rkcs>>kRKCS_V_FUNC)  & kRKCS_B_FUNC;
  uint16_t dr   = (fRd_rkda>>kRKDA_V_DRSEL) & kRKDA_B_DRSEL;
  Rw11UnitRK11& unit = *fspUnit[dr];
  Rw11Cpu& cpu = Cpu();
 
  uint8_t buf[512];
 
  if (fu == kRKCS_WRITE) {                  // Write -------------------------
                                            //   Note: WRITE+FMT is like WRITE
    RlinkCommandList clist;
    size_t bsize = (fRd_nwrd>256) ? 256 : fRd_nwrd;
    cpu.AddRMem(clist, fRd_addr, (uint16_t*) buf, bsize,
                Rw11Cpu::kCp_ah_m_22bit|Rw11Cpu::kCp_ah_m_ubmap);
    Server().Exec(clist);
    // FIXME_code: handle rdma I/O error
    RerrMsg emsg;
    bool rc = unit.VirtWrite(fRd_lba, 1, buf, emsg);
    if (!rc) {
      RlogMsg lmsg(LogFile());
      lmsg << emsg;
      rker |= kRKER_M_CSE;              // forward disk I/O error
    }
    if (rker == 0) {
      fRd_nwrd -= bsize;
      fRd_addr += 2*bsize;
      fRd_lba  += 1;
    }
    if (rker==0 && fRd_nwrd>0)            // not error and not yet done
      return 1;                           // requeue
 
  } else if (fu == kRKCS_READ) {
    if ((fRd_rkcs&kRKCS_M_FMT) == 0) {      // Read --------------------------
      RerrMsg emsg;
      bool rc = unit.VirtRead(fRd_lba, 1, buf, emsg);
      if (!rc) {
        RlogMsg lmsg(LogFile());
        lmsg << emsg;
        rker |= kRKER_M_CSE;              // forward disk I/O error
      }
 
      if (rker == 0) {
        RlinkCommandList clist;
        size_t bsize = (fRd_nwrd>256) ? 256 : fRd_nwrd;
        cpu.AddWMem(clist, fRd_addr, (uint16_t*) buf, bsize,
                    Rw11Cpu::kCp_ah_m_22bit|Rw11Cpu::kCp_ah_m_ubmap);
        Server().Exec(clist);
        // FIXME_code: handle rdma I/O error
        fRd_nwrd -= bsize;
        fRd_addr += 2*bsize;
        fRd_lba  += 1;
      }
      if (rker==0 && fRd_nwrd>0)            // not error and not yet done
        return 1;                           // requeue
 
    } else {                                // Read Format -------------------
      uint16_t cy = fRd_lba / (unit.NHead()*unit.NSector());
      uint16_t da = cy<<kRKDA_V_CYL;
      RlinkCommandList clist;
      cpu.AddWMem(clist, fRd_addr, &da, 1,
                  Rw11Cpu::kCp_ah_m_22bit|Rw11Cpu::kCp_ah_m_ubmap);
      Server().Exec(clist);
      // FIXME_code: handle rdma I/O error
      fRd_nwrd -= 1;
      fRd_addr += 2;
      fRd_lba  += 1;
      if (rker==0 && fRd_nwrd>0)            // not error and not yet done
        return 1;                           // requeue
    }
 
  } else if (fu == kRKCS_WCHK) {            // Write Check -------------------
    uint16_t bufmem[256];
    RlinkCommandList clist;
    size_t bsize = (fRd_nwrd>256) ? 256 : fRd_nwrd;
    cpu.AddRMem(clist, fRd_addr, bufmem, bsize,
                Rw11Cpu::kCp_ah_m_22bit|Rw11Cpu::kCp_ah_m_ubmap);
    Server().Exec(clist);
    // FIXME_code: handle rdma I/O error
    RerrMsg emsg;
    bool rc = unit.VirtRead(fRd_lba, 1, buf, emsg);
    if (!rc) {
      RlogMsg lmsg(LogFile());
      lmsg << emsg;
      rker |= kRKER_M_CSE;              // forward disk I/O error
    }
    if (rker == 0) {
      uint16_t* pmem = bufmem;
      uint16_t* pdsk = (uint16_t*) &buf;
      for (size_t i=0; i<bsize; i++) {
        if (*pmem++ != *pdsk++) rker |= kRKER_M_WCE;
      }
      fRd_nwrd -= bsize;
      fRd_addr += 2*bsize;
      fRd_lba  += 1;
    }
    // determine abort criterion
    bool stop = (rker & ~kRKER_M_WCE) != 0 ||
                ((rker & kRKER_M_WCE) && (fRd_rkcs & kRKCS_M_SSE));
    if (!stop && fRd_nwrd>0)                // not error and not yet done
      return 1;                             // requeue
 
  } else if (fu == kRKCS_RCHK) {            // Read Check --------------------
    // Note: no DMA transfer done; done here to keep logic similar to read
    size_t bsize = (fRd_nwrd>256) ? 256 : fRd_nwrd;
    fRd_nwrd -= bsize;
    fRd_addr += 2*bsize;
    fRd_lba  += 1;
    if (rker==0 && fRd_nwrd>0)            // not error and not yet done
      return 1;                           // requeue
 
  } else {
    throw Rexception("Rw11CntlDL11::RdmaHandler",
                     "Bad state: bad function code");
  }
 
  // common handling for dma transfer completion
  if (fRd_ovr) rker |= kRKER_M_OVR;
 
  RlinkCommandList clist;
 
  uint16_t ba   = fRd_addr & 0177776;       // get lower 16 bits
  uint16_t mex  = (fRd_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(fRd_lba, cy,hd,se);
  uint16_t da   = (fRd_rkda & kRKDA_M_DRSEL) | (cy<<kRKDA_V_CYL) |
                  (hd<<kRKDA_V_SUR) | se;
 
  cpu.AddIbrb(clist, fBase);
  if (rker) {
    cpu.AddWibr(clist, fBase+kRKER, rker);
    LogRker(rker);
  }
  cpu.AddWibr(clist, fBase+kRKWC, uint16_t((-fRd_nwrd)&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);
 
  Server().Exec(clist);
 
  fRd_busy  = false;
 
  return 0;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void Rw11CntlRK11::LogRker(uint16_t rker)
{
  RlogMsg lmsg(LogFile());
  lmsg << "-E RK11 er=" << RosPrintBvi(rker,8) << "  ERROR ABORT";
}
 
} // 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.