From 4cb079d5a02c677e3a648244b42704c4a5e55693 Mon Sep 17 00:00:00 2001 From: "Walter F.J. Mueller" Date: Mon, 17 Apr 2017 21:15:37 +0200 Subject: [PATCH] backend for DEUNA - Rw11CntlDEUNA: controller and almost all logic - Rw11UnitDEUNA: unit --- tools/src/librw11/Makefile | 3 + tools/src/librw11/Rw11CntlDEUNA.cpp | 1846 ++++++++++++++++++ tools/src/librw11/Rw11CntlDEUNA.hpp | 413 ++++ tools/src/librw11/Rw11CntlDEUNA.ipp | 134 ++ tools/src/librw11/Rw11UnitDEUNA.cpp | 90 + tools/src/librw11/Rw11UnitDEUNA.hpp | 61 + tools/src/librw11/Rw11UnitDEUNA.ipp | 44 + tools/src/librwxxtpp/Makefile | 1 + tools/src/librwxxtpp/RtclRw11CntlDEUNA.cpp | 127 ++ tools/src/librwxxtpp/RtclRw11CntlDEUNA.hpp | 50 + tools/src/librwxxtpp/RtclRw11CntlFactory.cpp | 13 +- tools/src/librwxxtpp/RtclRw11UnitDEUNA.cpp | 56 + tools/src/librwxxtpp/RtclRw11UnitDEUNA.hpp | 52 + tools/tcl/rw11/util.tcl | 11 +- 14 files changed, 2895 insertions(+), 6 deletions(-) create mode 100644 tools/src/librw11/Rw11CntlDEUNA.cpp create mode 100644 tools/src/librw11/Rw11CntlDEUNA.hpp create mode 100644 tools/src/librw11/Rw11CntlDEUNA.ipp create mode 100644 tools/src/librw11/Rw11UnitDEUNA.cpp create mode 100644 tools/src/librw11/Rw11UnitDEUNA.hpp create mode 100644 tools/src/librw11/Rw11UnitDEUNA.ipp create mode 100644 tools/src/librwxxtpp/RtclRw11CntlDEUNA.cpp create mode 100644 tools/src/librwxxtpp/RtclRw11CntlDEUNA.hpp create mode 100644 tools/src/librwxxtpp/RtclRw11UnitDEUNA.cpp create mode 100644 tools/src/librwxxtpp/RtclRw11UnitDEUNA.hpp diff --git a/tools/src/librw11/Makefile b/tools/src/librw11/Makefile index 8d876822..ecee870c 100644 --- a/tools/src/librw11/Makefile +++ b/tools/src/librw11/Makefile @@ -35,13 +35,16 @@ OBJ_all += Rw11CntlRL11.o Rw11UnitRL11.o OBJ_all += Rw11CntlRK11.o Rw11UnitRK11.o OBJ_all += Rw11CntlRHRP.o Rw11UnitRHRP.o OBJ_all += Rw11CntlTM11.o Rw11UnitTM11.o +OBJ_all += Rw11CntlDEUNA.o Rw11UnitDEUNA.o OBJ_all += Rw11Virt.o OBJ_all += Rw11VirtTerm.o Rw11VirtTermPty.o Rw11VirtTermTcp.o OBJ_all += Rw11VirtDiskBuffer.o OBJ_all += Rw11VirtDisk.o Rw11VirtDiskFile.o Rw11VirtDiskOver.o OBJ_all += Rw11VirtTape.o Rw11VirtTapeTap.o +OBJ_all += Rw11VirtEth.o Rw11VirtEthTap.o OBJ_all += Rw11VirtStream.o OBJ_all += Rw11Rdma.o Rw11RdmaDisk.o +OBJ_all += RethTools.o RethBuf.o # DEP_all = $(OBJ_all:.o=.dep) # diff --git a/tools/src/librw11/Rw11CntlDEUNA.cpp b/tools/src/librw11/Rw11CntlDEUNA.cpp new file mode 100644 index 00000000..f06193e9 --- /dev/null +++ b/tools/src/librw11/Rw11CntlDEUNA.cpp @@ -0,0 +1,1846 @@ +// $Id: Rw11CntlDEUNA.cpp 881 2017-04-17 18:52:26Z mueller $ +// +// Copyright 2014-2017 by Walter F.J. Mueller +// +// 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 +// 2017-04-17 880 0.5 Initial version (works w 211bsd; no err handling) +// 2014-06-09 561 0.1 First draft +// --------------------------------------------------------------------------- + +/*! + \file + \version $Id: Rw11CntlDEUNA.cpp 881 2017-04-17 18:52:26Z mueller $ + \brief Implemenation of Rw11CntlDEUNA. +*/ + +#include +#include +#include + +#include + +#include "boost/bind.hpp" + +#include "librtools/RosFill.hpp" +#include "librtools/RosPrintBvi.hpp" +#include "librtools/RosPrintf.hpp" +#include "librtools/Rexception.hpp" +#include "librtools/RlogMsg.hpp" +#include "librtools/Rtools.hpp" + +#include "RethTools.hpp" + +#include "Rw11CntlDEUNA.hpp" + +using namespace std; + +/*! + \class Retro::Rw11CntlDEUNA + \brief FIXME_docs +*/ + +// all method definitions in namespace Retro +namespace Retro { + +//------------------------------------------+----------------------------------- +// constants definitions + +const uint16_t Rw11CntlDEUNA::kIbaddr; +const int Rw11CntlDEUNA::kLam; + +const uint16_t Rw11CntlDEUNA::kPR0; +const uint16_t Rw11CntlDEUNA::kPR1; +const uint16_t Rw11CntlDEUNA::kPR2; +const uint16_t Rw11CntlDEUNA::kPR3; + +const uint16_t Rw11CntlDEUNA::kProbeOff; +const bool Rw11CntlDEUNA::kProbeInt; +const bool Rw11CntlDEUNA::kProbeRem; + +const uint16_t Rw11CntlDEUNA::kPR0_M_SERI; +const uint16_t Rw11CntlDEUNA::kPR0_M_PCEI; +const uint16_t Rw11CntlDEUNA::kPR0_M_RXI; +const uint16_t Rw11CntlDEUNA::kPR0_M_TXI; +const uint16_t Rw11CntlDEUNA::kPR0_M_DNI; +const uint16_t Rw11CntlDEUNA::kPR0_M_RCBI; +const uint16_t Rw11CntlDEUNA::kPR0_M_USCI; +const uint16_t Rw11CntlDEUNA::kPR0_M_INTR; +const uint16_t Rw11CntlDEUNA::kPR0_M_INTE; +const uint16_t Rw11CntlDEUNA::kPR0_M_RSET; +const uint16_t Rw11CntlDEUNA::kPR0_M_BRST; +const uint16_t Rw11CntlDEUNA::kPR0_M_PCMD; + +const uint16_t Rw11CntlDEUNA::kPR0_V_PCMDBP; +const uint16_t Rw11CntlDEUNA::kPR0_B_PCMDBP; +const uint16_t Rw11CntlDEUNA::kPR0_M_PCWWB; + +const uint16_t Rw11CntlDEUNA::kPCMD_NOOP; +const uint16_t Rw11CntlDEUNA::kPCMD_GETPCBB; +const uint16_t Rw11CntlDEUNA::kPCMD_GETCMD; +const uint16_t Rw11CntlDEUNA::kPCMD_SELFTST; +const uint16_t Rw11CntlDEUNA::kPCMD_START; +const uint16_t Rw11CntlDEUNA::kPCMD_BOOT; +const uint16_t Rw11CntlDEUNA::kPCMD_PDMD; +const uint16_t Rw11CntlDEUNA::kPCMD_HALT; +const uint16_t Rw11CntlDEUNA::kPCMD_STOP; + +const uint16_t Rw11CntlDEUNA::kPR1_M_XPWR; +const uint16_t Rw11CntlDEUNA::kPR1_M_ICAB; +const uint16_t Rw11CntlDEUNA::kPR1_M_PCTO; +const uint16_t Rw11CntlDEUNA::kPR1_M_DELUA; +const uint16_t Rw11CntlDEUNA::kPR1_M_STATE; + +const uint16_t Rw11CntlDEUNA::kSTATE_RESET; +const uint16_t Rw11CntlDEUNA::kSTATE_PLOAD; +const uint16_t Rw11CntlDEUNA::kSTATE_READY; +const uint16_t Rw11CntlDEUNA::kSTATE_RUN; +const uint16_t Rw11CntlDEUNA::kSTATE_UHALT; +const uint16_t Rw11CntlDEUNA::kSTATE_NHALT; +const uint16_t Rw11CntlDEUNA::kSTATE_NUHALT; +const uint16_t Rw11CntlDEUNA::kSTATE_PHALT; +const uint16_t Rw11CntlDEUNA::kSTATE_SLOAD; + +const uint16_t Rw11CntlDEUNA::kPC0_M_FUNC; +const uint16_t Rw11CntlDEUNA::kPC0_M_MBZ; + +const uint16_t Rw11CntlDEUNA::kFUNC_NOOP; +const uint16_t Rw11CntlDEUNA::kFUNC_RDPA; +const uint16_t Rw11CntlDEUNA::kFUNC_RPA; +const uint16_t Rw11CntlDEUNA::kFUNC_WPA; +const uint16_t Rw11CntlDEUNA::kFUNC_RMAL; +const uint16_t Rw11CntlDEUNA::kFUNC_WMAL; +const uint16_t Rw11CntlDEUNA::kFUNC_RRF; +const uint16_t Rw11CntlDEUNA::kFUNC_WRF; +const uint16_t Rw11CntlDEUNA::kFUNC_RCTR; +const uint16_t Rw11CntlDEUNA::kFUNC_RCCTR; +const uint16_t Rw11CntlDEUNA::kFUNC_RMODE; +const uint16_t Rw11CntlDEUNA::kFUNC_WMODE; +const uint16_t Rw11CntlDEUNA::kFUNC_RSTAT; +const uint16_t Rw11CntlDEUNA::kFUNC_RCSTAT; +const uint16_t Rw11CntlDEUNA::kFUNC_RSID; +const uint16_t Rw11CntlDEUNA::kFUNC_WSID; + +const uint16_t Rw11CntlDEUNA::kSTAT_M_ERRS; +const uint16_t Rw11CntlDEUNA::kSTAT_M_MERR; +const uint16_t Rw11CntlDEUNA::kSTAT_M_BABL; +const uint16_t Rw11CntlDEUNA::kSTAT_M_CERR; +const uint16_t Rw11CntlDEUNA::kSTAT_M_TMOT; +const uint16_t Rw11CntlDEUNA::kSTAT_M_RRNG; +const uint16_t Rw11CntlDEUNA::kSTAT_M_TRNG; +const uint16_t Rw11CntlDEUNA::kSTAT_M_PTCH; +const uint16_t Rw11CntlDEUNA::kSTAT_M_RRAM; +const uint16_t Rw11CntlDEUNA::kSTAT_M_RREV; + +const uint16_t Rw11CntlDEUNA::kMODE_M_PROM; +const uint16_t Rw11CntlDEUNA::kMODE_M_ENAL; +const uint16_t Rw11CntlDEUNA::kMODE_M_DRDC; +const uint16_t Rw11CntlDEUNA::kMODE_M_TPAD; +const uint16_t Rw11CntlDEUNA::kMODE_M_ECT; +const uint16_t Rw11CntlDEUNA::kMODE_M_DMNT; +const uint16_t Rw11CntlDEUNA::kMODE_M_INTL; +const uint16_t Rw11CntlDEUNA::kMODE_M_DTCR; +const uint16_t Rw11CntlDEUNA::kMODE_M_LOOP; +const uint16_t Rw11CntlDEUNA::kMODE_M_HDPX; +const uint16_t Rw11CntlDEUNA::kMODE_M_MBZ_DEUNA; +const uint16_t Rw11CntlDEUNA::kMODE_M_MBZ_DELUA; + +const uint16_t Rw11CntlDEUNA::kTXR2_M_OWN; +const uint16_t Rw11CntlDEUNA::kTXR2_M_ERRS; +const uint16_t Rw11CntlDEUNA::kTXR2_M_MTCH; +const uint16_t Rw11CntlDEUNA::kTXR2_M_MORE; +const uint16_t Rw11CntlDEUNA::kTXR2_M_ONE; +const uint16_t Rw11CntlDEUNA::kTXR2_M_DEF; +const uint16_t Rw11CntlDEUNA::kTXR2_M_STF; +const uint16_t Rw11CntlDEUNA::kTXR2_M_ENF; +const uint16_t Rw11CntlDEUNA::kTXR2_M_SEGB; +const uint16_t Rw11CntlDEUNA::kTXR3_M_BUFL; +const uint16_t Rw11CntlDEUNA::kTXR3_M_UBTO; +const uint16_t Rw11CntlDEUNA::kTXR3_M_UFLO; +const uint16_t Rw11CntlDEUNA::kTXR3_M_LCOL; +const uint16_t Rw11CntlDEUNA::kTXR3_M_LCAR; +const uint16_t Rw11CntlDEUNA::kTXR3_M_RTRY; +const uint16_t Rw11CntlDEUNA::kTXR3_M_TDR; + +const uint16_t Rw11CntlDEUNA::kRXR2_M_OWN; +const uint16_t Rw11CntlDEUNA::kRXR2_M_ERRS; +const uint16_t Rw11CntlDEUNA::kRXR2_M_FRAM; +const uint16_t Rw11CntlDEUNA::kRXR2_M_OFLO; +const uint16_t Rw11CntlDEUNA::kRXR2_M_CRC; +const uint16_t Rw11CntlDEUNA::kRXR2_M_STF; +const uint16_t Rw11CntlDEUNA::kRXR2_M_ENF; +const uint16_t Rw11CntlDEUNA::kRXR2_M_SEGB; +const uint16_t Rw11CntlDEUNA::kRXR3_M_BUFL; +const uint16_t Rw11CntlDEUNA::kRXR3_M_UBTO; +const uint16_t Rw11CntlDEUNA::kRXR3_M_NCHN; +const uint16_t Rw11CntlDEUNA::kRXR3_M_OVRN; +const uint16_t Rw11CntlDEUNA::kRXR3_M_MLEN; + +const uint32_t Rw11CntlDEUNA::kUBA_M; +const uint32_t Rw11CntlDEUNA::kUBAODD_M; +const uint16_t Rw11CntlDEUNA::kDimMcast; +const uint16_t Rw11CntlDEUNA::kDimCtrDeuna; +const uint16_t Rw11CntlDEUNA::kDimCtrDelua; +const uint16_t Rw11CntlDEUNA::kDimCtr; + +//------------------------------------------+----------------------------------- +//! Default constructor + +Rw11CntlDEUNA::Rw11CntlDEUNA() + : Rw11CntlBase("deuna"), + fPC_rdpr0(0), + fPC_rdpcb(0), + fPC_lapcb(0), + fPC_rdtxdsccur(0), + fPC_latxdsccur(0), + fPC_rdtxdscnxt(0), + fPC_latxdscnxt(0), + fPC_rdrxdsccur(0), + fPC_larxdsccur(0), + fPC_rdrxdscnxt(0), + fPcbbValid(false), + fPcbb(0), + fRingValid(false), + fTxRingBase(0), + fTxRingSize(0), + fTxRingELen(0), + fRxRingBase(0), + fRxRingSize(0), + fRxRingELen(0), + fMacDefault(RethTools::String2Mac("08:00:2b:00:00:00")), + fPr0Last(0), + fPr1Pcto(false), + fPr1Delua(false), + fPr1State(kSTATE_RESET), + fRunning(false), + fMode(0), + fStatus(0), + fTxRingIndex(0), + fRxRingIndex(0), + fTxRingState(kStateTxIdle), + fTxBuf(), + fTxBufOffset(0), + fRxRingState(kStateRxIdle), + fRxPollTime(0.01), + fRxQueLimit(1000), + fRxPollTimer(), + fRxBufQueue(), + fRxBufCurr(), + fRxBufOffset(0) +{ + // must be here because Units have a back-ptr (not available at Rw11CntlBase) + fspUnit[0].reset(new Rw11UnitDEUNA(this, 0)); // single unit controller + + ClearMacList(); + ClearCtr(); + + // setup fStats + fStats.Define(kStatNPcmdNoop , "NPcmdNoop" , "pcmd NOOP (spurious)"); + fStats.Define(kStatNPcmdGetpcbb, "NPcmdGetpcbb", "pcmd GETPCBB"); + fStats.Define(kStatNPcmdGetcmd , "NPcmdGetcmd" , "pcmd GETCMD"); + fStats.Define(kStatNPcmdSelftst, "NPcmdSelftst", "pcmd SELFTST"); + fStats.Define(kStatNPcmdStart , "NPcmdStart" , "pcmd START"); + fStats.Define(kStatNPcmdPdmd , "NPcmdPdmd" , "pcmd PDMD"); + fStats.Define(kStatNPcmdStop , "NPcmdStop" , "pcmd STOP"); + fStats.Define(kStatNPcmdHalt , "NPcmdHalt" , "pcmd HALT"); + fStats.Define(kStatNPcmdRsrvd , "NPcmdRsrvd" , "pcmd reserved"); + fStats.Define(kStatNPcmdUimpl , "NPcmdUimpl" , "pcmd not implemented"); + fStats.Define(kStatNFuncNoop , "NFuncNoop" , "func NOOP"); + fStats.Define(kStatNFuncRdpa , "NFuncRdpa" , "func RDPA"); + fStats.Define(kStatNFuncRpa , "NFuncRpa" , "func PRA"); + fStats.Define(kStatNFuncWpa , "NFuncWpa" , "func WPA"); + fStats.Define(kStatNFuncRmal , "NFuncRmal" , "func RMAL"); + fStats.Define(kStatNFuncWmal , "NFuncWmal" , "func WMAL"); + fStats.Define(kStatNFuncRrf , "NFuncRrf" , "func RRF"); + fStats.Define(kStatNFuncWrf , "NFuncWrf" , "func WRF"); + fStats.Define(kStatNFuncRctr , "NFuncRctr" , "func RCTR"); + fStats.Define(kStatNFuncRcctr , "NFuncRcctr" , "func RCCTR"); + fStats.Define(kStatNFuncRmode , "NFuncRmode" , "func RMODE"); + fStats.Define(kStatNFuncWmode , "NFuncWmode" , "func WMODE"); + fStats.Define(kStatNFuncRstat , "NFuncRstat" , "func RSTAT"); + fStats.Define(kStatNFuncRcstat , "NFuncRcstat" , "func RCSTAT"); + fStats.Define(kStatNFuncRsid , "NFuncRsid" , "func RSID"); + fStats.Define(kStatNFuncWsid , "NFuncWsid" , "func WSID"); + fStats.Define(kStatNFuncUimpl , "NFuncUimpl" , "func not implemented"); + fStats.Define(kStatNRxFraSeen , "NRxFraSeen" , "in frames seen"); + fStats.Define(kStatNRxFraFDst , "NRxFraFDst" , "in frames match dst mac"); + fStats.Define(kStatNRxFraFBcast, "NRxFraFBcast", "in frames match bcast"); + fStats.Define(kStatNRxFraFMcast, "NRxFraFMcast", "in frames match mcast"); + fStats.Define(kStatNRxFraFProm , "NRxFraFProm" , "in frames promiscous"); + fStats.Define(kStatNRxFraFUDrop, "NRxFraFUDrop", "in frames drop miss mac"); + fStats.Define(kStatNRxFraFMDrop, "NRxFraFMDrop", "in frames drop miss mcast"); + fStats.Define(kStatNRxFraQLDrop, "NRxFraQLDrop", "in frames drop drop"); + fStats.Define(kStatNRxFraNRDrop, "NRxFraNRDrop", "in frames drop not running"); + fStats.Define(kStatNRxFra , "NRxFra" , "rcvd frames"); + fStats.Define(kStatNRxFraMcast , "NRxFraMcast" , "rcvd bcast+mcast frames"); + fStats.Define(kStatNRxFraBcast , "NRxFraBcast" , "rcvd bcast frames"); + fStats.Define(kStatNRxByt , "NRxByt" , "rcvd bytes"); + fStats.Define(kStatNRxBytMcast , "NRxBytMcast" , "rcvd mcast bytes"); + fStats.Define(kStatNRxFraLoInt , "NRxFraLoInt" , "lost frames int err "); + fStats.Define(kStatNRxFraLoBuf , "NRxFraLoBuf" , "lost frames buffer"); + fStats.Define(kStatNRxFraPad , "NRxFraPad" , "rcvd padded frames"); + fStats.Define(kStatNTxFra , "NTxFra" , "xmit frames"); + fStats.Define(kStatNTxFraMcast , "NTxFraMcast" , "xmit bcast+mcast frames"); + fStats.Define(kStatNTxFraBcast , "NTxFraBcast" , "xmit bcast frames"); + fStats.Define(kStatNTxByt , "NTxByt" , "xmit bytes"); + fStats.Define(kStatNTxBytMcast , "NTxBytMcast" , "xmit mcast bytes"); + fStats.Define(kStatNTxFraAbort , "NTxFraAbort" , "xmit aborted frames"); + fStats.Define(kStatNTxFraPad , "NTxFraPad" , "xmit padded frames"); + fStats.Define(kStatNFraLoop , "NFraLoop" , "loopback frames"); +} + +//------------------------------------------+----------------------------------- +//! Destructor + +Rw11CntlDEUNA::~Rw11CntlDEUNA() +{} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11CntlDEUNA::Config(const std::string& name, uint16_t base, int lam) +{ + ConfigCntl(name, base, lam, kProbeOff, kProbeInt, kProbeRem); + return; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11CntlDEUNA::Start() +{ + if (fStarted || fLam<0 || !fEnable || !fProbe.Found()) + throw Rexception("Rw11CntlDEUNA::Start", + "Bad state: started, no lam, not enabled, not found"); + + // add device register address ibus and rbus mappings + // done here because now Cntl bound to Cpu and Cntl probed + Cpu().AllIAddrMapInsert(Name()+".pr0", Base() + kPR0); + Cpu().AllIAddrMapInsert(Name()+".pr1", Base() + kPR1); + Cpu().AllIAddrMapInsert(Name()+".pr2", Base() + kPR2); + Cpu().AllIAddrMapInsert(Name()+".pr3", Base() + kPR3); + + // setup primary info clist + SetupPrimClist(); + + fPr1State = kSTATE_READY; + UnitSetup(0); + + // add attn handler + Server().AddAttnHandler(boost::bind(&Rw11CntlDEUNA::AttnHandler, this, _1), + uint16_t(1)<Virt()) + throw Rexception("Rw11CntlDEUNA::SetType", + string("Bad state: not in READY state or attached")); + + if (type == "deuna") { + fPr1Delua = false; + } else if (type == "delua") { + fPr1Delua = true; + } else { + throw Rexception("Rw11CntlDEUNA::SetType", + string("Bad args: only deuna or delua supported")); + } + fType = type; + UnitSetup(0); + return; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs +// allow xx:xx:xx:xx:xx:xx +// random --> random mac, with 1st bit=0; 2nd bit=1 (LAA) +// dec:xx:xx:xx --> 08:00:0b:xx:xx:xx --> DEC OUI +// retro::xx --> 52:65:74:72:6f:xx --> ascii 'Retro' +// 'R' = 52 -> 2nd bit = 1 -> locally administered address + +void Rw11CntlDEUNA::SetMacDefault(const std::string& mac) +{ + string machex = mac; + uint64_t bmac; + const uint64_t macbit1 = 0x1; + const uint64_t macbit2 = 0x2; + + if (mac == "random") { + int fd = ::open("/dev/urandom",O_RDONLY); + if (fd < 0) + throw Rexception("Rw11CntlDEUNA::SetMacDefault", + "open() for '/dev/urandom' failed: ", errno); + + if (::read(fd, &bmac, sizeof(bmac)) != sizeof(bmac)) + throw Rexception("Rw11CntlDEUNA::SetMacDefault", + "read() for '/dev/random' failed: ", errno); + bmac &= ~macbit1; // ensure bcast bit is clear + bmac |= macbit2; // ensure laa bit is set + + } else { + if (mac.substr(0,4) == "dec:") { + machex = "08:00:0b:"; // DEC OUI + machex += mac.substr(4); + } else if (mac.substr(0,6) == "retro:") { + machex = "52:65:74:72:6f:"; // ascii 'Retro'; 52 -> LAA + machex += mac.substr(6); + } + + bmac = RethTools::String2Mac(machex); + } + + if (bmac & macbit1) + throw Rexception("Rw11CntlDEUNA::SetMacDefault", + string("Bad args: mcast address given, lsb not 0")); + if (fPr1State == kSTATE_READY && // if not running + (!fspUnit[0]->Virt()) && // and not attached + fMacList[0] == fMacDefault) { // and old pa was old dpa + fMacList[0] = bmac; // update also pa ! + } + fMacDefault = bmac; // and always dpa ! + return; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11CntlDEUNA::SetRxPollTime(const Rtime& time) +{ + if (!time.IsPositive()) + throw Rexception("Rw11CntlDEUNA::SetRxPollTime", + string("Bad args: time <= 0")); + fRxPollTime = time; + return; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11CntlDEUNA::SetRxQueLimit(size_t rxqlim) +{ + if (rxqlim <= 0) + throw Rexception("Rw11CntlDEUNA::SetRxQueLimit", + string("Bad args: rxqlim <= 0")); + fRxQueLimit = rxqlim; + return; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs + +std::string Rw11CntlDEUNA::MacDefault() const +{ + return RethTools::Mac2String(fMacDefault); +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs + +const char* Rw11CntlDEUNA::MnemoPcmd(uint16_t pcmd) const +{ + static const char* mnemopcmd[16] = {"noop ","getpcb","getcmd","slftst", + "start ","boot ","rsrv06","rsrv07", + "pdmd ","rsrv11","rsrv12","rsrv13", + "rsrv14","rsrv15","halt ","stop "}; + if (pcmd >= 16) return "??????"; + return mnemopcmd[pcmd]; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs + +const char* Rw11CntlDEUNA::MnemoFunc(uint16_t func) const +{ + static const char* mnemofunc[32] = {"noop ","uimp01","rdpa ","noop03", + "rpa ","wpa ","rmal ","wmal ", + "rrf ","wrf ","rctr ","rcctr ", + "rmode ","wmode ","rstat ","rcstat", + "uimp20","uimp21","rsid ","wsid ", + "uimp24","uimp25","uimp26","uimp27", + "uimp30","uimp31","uimp32","uimp33", + "uimp34","uimp35","uimp36","uimp37"}; + if (func >= 32) return "??????"; + return mnemofunc[func]; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs + +const char* Rw11CntlDEUNA::MnemoState(uint16_t state) const +{ + static const char* mnemostate[16] = {"reset ","pload ","ready ","run ", + "rsrv04","uhalt ","nhalt ","nuhalt", + "phalt ","rsrv11","rsrv12","rsrv13", + "rsrv14","rsrv15","rsrv16","sload "}; + if (state >= 16) return "??????"; + return mnemostate[state]; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +bool Rw11CntlDEUNA::RcvCallback(RethBuf::pbuf_t& pbuf) +{ + // lock connect to protect rxqueue + boost::lock_guard lock(Connect()); + + fStats.Inc(kStatNRxFraSeen); + if (!Running()) { // drop if not running + fStats.Inc(kStatNRxFraNRDrop); + return true; + } + + uint64_t macdst = pbuf->MacDestination(); + int matchdst = MacFilter(macdst); + + if (matchdst < 0) { // not matched ? + if (fMode & kMODE_M_PROM) { // promiscous mode + fStats.Inc(kStatNRxFraFProm); // count and accept + } else { // otherwise drop + if (matchdst & 0x1) { // mcast address + fStats.Inc(kStatNRxFraFMDrop); + } else { + fStats.Inc(kStatNRxFraFUDrop); + } + if (fTraceLevel>1) { + RlogMsg lmsg(LogFile()); + lmsg << "-I " << Name() << ": fdrop " << pbuf->FrameInfo() << endl; + } + return true; + } + } else { // machted + if (matchdst == 0) { + fStats.Inc(kStatNRxFraFDst); + } else if (matchdst == 1) { + fStats.Inc(kStatNRxFraFBcast); + } else { + fStats.Inc(kStatNRxFraFMcast); + } + } + + if (fRxBufQueue.size() >= fRxQueLimit) { // drop if queue too long + fStats.Inc(kStatNRxFraQLDrop); + if (fTraceLevel>0) { + RlogMsg lmsg(LogFile()); + lmsg << "-I " << Name() << ": qdrop " << pbuf->FrameInfo() << endl; + } + return true; + } + + fRxBufQueue.push_back(pbuf); + + // FIXME_code: can we (should we) use last cached dscs ??? + if (fTxRingState == kStateTxIdle) StartRxRing(); + + return true; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11CntlDEUNA::Dump(std::ostream& os, int ind, const char* text, + int detail) const +{ + // lock connect to protect, e.g fRxBufQueue access + boost::lock_guard lock(Connect()); + + RosFill bl(ind); + os << bl << (text?text:"--") << "Rw11CntlDEUNA @ " << this << endl; + os << bl << " fPC_rdpr0: " << fPC_rdpr0 << endl; + os << bl << " fPC_rdpcb: " << fPC_rdpcb << endl; + os << bl << " fPC_lapcb: " << fPC_lapcb << endl; + os << bl << " fPC_rdtxdsccur: " << fPC_rdtxdsccur << endl; + os << bl << " fPC_latxdsccur: " << fPC_latxdsccur << endl; + os << bl << " fPC_rdtxdscnxt: " << fPC_rdtxdscnxt << endl; + os << bl << " fPC_latxdscnxt: " << fPC_latxdscnxt << endl; + os << bl << " fPC_rdrxdsccur: " << fPC_rdrxdsccur << endl; + os << bl << " fPC_larxdsccur: " << fPC_larxdsccur << endl; + os << bl << " fPC_rdrxdscnxt: " << fPC_rdrxdscnxt << endl; + os << bl << " fPcbbValid: " << fPcbbValid << endl; + os << bl << " fPcbb: " << RosPrintf(fPcbb,"o0", 6) << endl; + os << bl << " fPcb: "; + for (auto& v : fPcb) os << " " << RosPrintf(v,"o0", 6); + os << endl; + + os << bl << " fRingValid: " << fRingValid << endl; + os << bl << " fTxRing format: " << RosPrintf(fTxRingBase,"o0", 7) + << "," << RosPrintf(fTxRingSize,"d", 3) + << "," << RosPrintf(fTxRingELen,"d", 3) << endl; + os << bl << " fRxRing format: " << RosPrintf(fRxRingBase,"o0", 7) + << "," << RosPrintf(fRxRingSize,"d", 3) + << "," << RosPrintf(fRxRingELen,"d", 3) << endl; + + os << bl << " fMacDefault: " + << RosPrintf(fMacDefault,"x0",12) << " " + << RethTools::Mac2String(fMacDefault) << endl; + os << bl << " fMacList[0]: " + << RosPrintf(fMacList[0],"x0",12) << " " + << RethTools::Mac2String(fMacList[0]) << endl; + os << bl << " fMacList[1]: " + << RosPrintf(fMacList[1],"x0",12) << " " + << RethTools::Mac2String(fMacList[1]) << endl; + os << bl << " fMacastCnt: " << RosPrintf(fMcastCnt,"d", 2) << endl; + for (int i=0; iFrameInfo() << endl; + } + if (fRxBufCurr) { + fRxBufCurr->Dump(os, ind+2, "fRxBufCurr:", detail); + } else { + os << bl << " fRxBufCurr: " << "null" << endl; + } + os << bl << " fCtrTimeCleared: " + << RosPrintf(fCtrTimeCleared.Age(CLOCK_MONOTONIC),"f",10,2) << endl; + os << bl << " fCtrRxFra: " + << RosPrintf(fCtrRxFra,"d",10) << endl; + os << bl << " fCtrRxFraMcast: " + << RosPrintf(fCtrRxFraMcast,"d",10) << endl; + os << bl << " fCtrRxByt: " + << RosPrintf(fCtrRxByt,"d",10) << endl; + os << bl << " fCtrRxBytMcast: " + << RosPrintf(fCtrRxBytMcast,"d",10) << endl; + os << bl << " fCtrRxFraLoInt: " + << RosPrintf(fCtrRxFraLoInt,"d",10) << endl; + os << bl << " fCtrRxFraLoBuf: " + << RosPrintf(fCtrRxFraLoBuf,"d",10) << endl; + os << bl << " fCtrTxFra: " + << RosPrintf(fCtrTxFra,"d",10) << endl; + os << bl << " fCtrTxFraMcast: " + << RosPrintf(fCtrTxFraMcast,"d",10) << endl; + os << bl << " fCtrTxByt: " + << RosPrintf(fCtrTxByt,"d",10) << endl; + os << bl << " fCtrTxBytMcast: " + << RosPrintf(fCtrTxBytMcast,"d",10) << endl; + os << bl << " fCtrTxFraAbort: " + << RosPrintf(fCtrTxFraAbort,"d",10) << endl; + os << bl << " fCtrFramesLoop: " + << RosPrintf(fCtrFraLoop,"d",10) << endl; + Rw11CntlBase::Dump(os, ind, " ^", detail); + return; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs + +// summary of log entry +// handler lines +// -I xua: cmd pr0=oooooo rset=b brst=b +// -I xua: cmd pr0=000110 cmd=...... +// -I xua: cmd pr0=000110 cmd=pdmd t00,OSE,OSE r00,OSE,OSE +// -I xua: cmd pr0=oooooo cmd=getcmd fu=...... udbb=oooooo +// -I xua: txr t00 < dddd,oooooo,dddd; bbbbbbbb,bbbb: OSE, ... +// -I xua: snd 00:00:00:00:00:00 > 00:00:00:00:00:00 typ: xxxx len: dddd +// command specific lines +// -I xua: GETPCBB: oooooo +// -I xua: RPA: 08:00:2b:00:00:00 +// -I xua: WRF: tx base=oooooo size=dd elen=dd; rx base=oooooo size=dd elen=dd +// -I xua: WMODE: mode=oooooo + + +int Rw11CntlDEUNA::AttnHandler(RlinkServer::AttnArgs& args) +{ + fStats.Inc(kStatNAttnHdl); + + Rw11Cpu& cpu = Cpu(); + if (fPC_rdtxdsccur > 0) { // txdsc read update, if setup + cpu.ModLalh(fPrimClist, fPC_rdtxdsccur, TxRingDscAddr(fTxRingIndex), + Rw11Cpu::kCPAH_M_UBM22); + cpu.ModLalh(fPrimClist, fPC_rdtxdscnxt, TxRingDscAddr(TxRingIndexNext()), + Rw11Cpu::kCPAH_M_UBM22); + cpu.ModLalh(fPrimClist, fPC_rdrxdsccur, RxRingDscAddr(fRxRingIndex), + Rw11Cpu::kCPAH_M_UBM22); + cpu.ModLalh(fPrimClist, fPC_rdrxdscnxt, RxRingDscAddr(RxRingIndexNext()), + Rw11Cpu::kCPAH_M_UBM22); + } + + Server().GetAttnInfo(args, fPrimClist); + // FIXME_code: handle pcb and txdsc read errors ... + + fPr0Last = fPrimClist[fPC_rdpr0].Data(); + + bool rset = fPr0Last & kPR0_M_RSET; + bool brst = fPr0Last & kPR0_M_BRST; + uint16_t pcmd = (fPr0Last>>kPR0_V_PCMDBP) & kPR0_B_PCMDBP; + + // check for pcmd write while busy (part 1) + if (fPr0Last & kPR0_M_PCWWB) { + RlogMsg lmsg(LogFile()); + lmsg << "-E " << Name() << ": pcmd race" + << " pr0=" << RosPrintBvi(fPr0Last,8) + << " pcmd-1st=" << MnemoPcmd(pcmd) + << " pcmd-2nd=" << MnemoPcmd(fPr0Last & kPR0_M_PCMD); + } + + RlinkCommandList clist; + + fPr1Pcto = false; + uint16_t pr0out = 0; + + // handle bus and software reset: stop runnig, poll for RingHandler run-down + if (rset || brst) { + if (fTraceLevel>0) { + RlogMsg lmsg(LogFile()); + lmsg << "-I " << Name() << ": cmd" + << " pr0=" << RosPrintBvi(fPr0Last,8) + << " rset=" << rset << " brst=" << brst; + } + Reset(); + if (rset) pr0out |= kPR0_M_RSET|kPR0_M_DNI; + if (brst) pr0out |= kPR0_M_BRST; + cpu.AddWibr(clist, fBase+kPR1, GetPr1()); + cpu.AddWibr(clist, fBase+kPR0, pr0out); + Server().Exec(clist); + return 0; + } + + if (fTraceLevel>0) { + RlogMsg lmsg(LogFile()); + lmsg << "-I " << Name() << ": cmd" + << " pr0=" << RosPrintBvi(fPr0Last,8) + << " r=" << rset << "," << brst + << " cmd=" << MnemoPcmd(pcmd); + + if (pcmd == kPCMD_GETCMD && fPC_rdpcb > 0) { // if GETCMD and pdb loaded + uint16_t func = fPcb[0] & kPC0_M_FUNC; + lmsg << " fu=" << MnemoFunc(func); + + if (func == kFUNC_RMAL || func == kFUNC_WMAL || // if func with udbb + func == kFUNC_RRF || func == kFUNC_WRF || + func == kFUNC_RCTR || func == kFUNC_RCCTR || + func == kFUNC_RSID || func == kFUNC_WSID) { + uint32_t udbb = 0777777; + Wlist2UBAddr(&fPcb[1], udbb); + lmsg << " udbb=" << RosPrintf(udbb&kUBA_M,"o0", 6); + } + } + if (pcmd == kPCMD_PDMD && fPC_rdtxdsccur > 0) { // PDMD and txdsc ect loaded + lmsg << " t" << RosPrintf(fTxRingIndex,"d0", 2) + << "," << RingDsc2OSEString(fTxDscCurPC,'-') + << "," << RingDsc2OSEString(fTxDscNxtPC,'-') + << " r" << RosPrintf(fRxRingIndex,"d0", 2) + << "," << RingDsc2OSEString(fRxDscCurPC,'-') + << "," << RingDsc2OSEString(fRxDscNxtPC,'-'); + } + } + + switch (pcmd) { + case kPCMD_NOOP: // NOOP -------------------------- + fStats.Inc(kStatNPcmdNoop); + return 0; // fully handled in FPGA + + case kPCMD_GETPCBB: // GETPCBB ----------------------- + { + fStats.Inc(kStatNPcmdGetpcbb); + size_t ipr2 = cpu.AddRibr(clist, fBase+kPR2); + size_t ipr3 = cpu.AddRibr(clist, fBase+kPR3); + cpu.AddWibr(clist, fBase+kPR1, GetPr1()); + cpu.AddWibr(clist, fBase+kPR0, kPR0_M_DNI); + Server().Exec(clist); + fPcbb = ( uint32_t(clist[ipr2].Data()) | + (uint32_t(clist[ipr3].Data())<<16)) & kUBA_M; // 17:01 valid! + fPcbbValid = true; + SetupPrimClist(); + if (fTraceLevel>0) { + RlogMsg lmsg(LogFile()); + lmsg << "-I " << Name() << ": GETPCBB: " << RosPrintBvi(fPcbb,8,18); + } + } + return 0; + + case kPCMD_GETCMD: // GETCMD ------------------------ + { + fStats.Inc(kStatNPcmdGetcmd); + bool ok = ExecGetcmd(clist); + pr0out |= ok ? kPR0_M_DNI : kPR0_M_PCEI; + } + break; + + case kPCMD_SELFTST: // SELFTST ----------------------- + { + fStats.Inc(kStatNPcmdSelftst); + Reset(); // handle like reset + pr0out |= kPR0_M_DNI; + } + return 0; + + case kPCMD_START: // START ------------------------- + { + fStats.Inc(kStatNPcmdStart); + if (fPr1State == kSTATE_RUN) { // start while running is a noop + pr0out |= kPR0_M_DNI; + break; + } + if (fPr1State == kSTATE_READY && fRingValid) { // in _READY and ring ok + SetRunning(true); + pr0out |= kPR0_M_DNI; + } else { + pr0out |= kPR0_M_PCEI; + } + } + break; + + case kPCMD_BOOT: // BOOT -------------------------- + { + fStats.Inc(kStatNPcmdUimpl); // not implemented ... + pr0out |= kPR0_M_PCEI; + } + break; + + case kPCMD_PDMD: // PDMD -------------------------- + { + fStats.Inc(kStatNPcmdPdmd); + if (Running()) { + StartTxRing(fTxDscCurPC, fTxDscNxtPC); + StartRxRing(fRxDscCurPC, fRxDscNxtPC); + } + pr0out |= kPR0_M_DNI; + } + break; + + case kPCMD_HALT: // HALT -------------------------- + { + if (fPr1Delua) { + fStats.Inc(kStatNPcmdHalt); // defined for DELUA + SetRunning(false); + fPr1State = kSTATE_PHALT; // ends in dead end state + } else { + fStats.Inc(kStatNPcmdRsrvd); + } + pr0out |= kPR0_M_DNI; // always DNI it (is noop on DEUNA) + } + break; + + case kPCMD_STOP: // STOP -------------------------- + { + fStats.Inc(kStatNPcmdStop); + if (fPr1State == kSTATE_RUN) { // stop if in _RUN, noop otherwise + SetRunning(false); + } + pr0out |= kPR0_M_PCEI; + } + break; + + default: // all others are reserved codes + { + fStats.Inc(kStatNPcmdRsrvd); + pr0out |= kPR0_M_DNI; + } + break; + } + + cpu.AddWibr(clist, fBase+kPR1, GetPr1()); + cpu.AddWibr(clist, fBase+kPR0, pr0out); + Server().Exec(clist); + return 0; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11CntlDEUNA::ClearMacList() +{ + for (auto& mac : fMacList) mac = 0; + fMacList[0] = fMacDefault; + fMacList[1] = 0xffffffffffff; + fMcastCnt = 0; + return; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11CntlDEUNA::ClearCtr() +{ + fCtrTimeCleared.GetClock(CLOCK_MONOTONIC); + fCtrRxFra = 0; + fCtrRxFraMcast = 0; + fCtrRxByt = 0; + fCtrRxBytMcast = 0; + fCtrRxFraLoInt = 0; + fCtrRxFraLoBuf = 0; + fCtrTxFra = 0; + fCtrTxFraMcast = 0; + fCtrTxByt = 0; + fCtrTxBytMcast = 0; + fCtrTxFraAbort = 0; + fCtrFraLoop = 0; + return; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11CntlDEUNA::ClearStatus() +{ + fStatus = 0; // lsb is 0 anyway. so clear all + return; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +void Rw11CntlDEUNA::Reset() +{ + fRunning = false; // end running + StopTxRing(); // run-down tx ring + StopRxRing(); // run-down rx ring + fPcbbValid = false; // clear state + fPcbb = 0; + fRingValid = false; + fTxRingBase = 0; + fTxRingSize = 0; + fTxRingELen = 0; + fRxRingBase = 0; + fRxRingSize = 0; + fRxRingELen = 0; + fTxRingIndex = 0; + fRxRingIndex = 0; + fMacList[0] = fMacDefault; + fMcastCnt = 0; + fPr1Pcto = false; + fPr1State = kSTATE_READY; + SetupPrimClist(); + ClearStatus(); + ClearCtr(); + return; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +void Rw11CntlDEUNA::SetRunning(bool run) +{ + if (fRunning == run) return; + if (run) { // start + if (! fRxPollTimer.IsOpen()) { // start poll timer if needed + fRxPollTimer.Open(); + Server().AddPollHandler(boost::bind(&Rw11CntlDEUNA::RxPollHandler, + this, _1), + fRxPollTimer.Fd(), POLLIN); + } + + fRunning = true; + fPr1State = kSTATE_RUN; + fTxRingIndex = 0; + fTxBufOffset = 0; + fRxRingIndex = 0; + fRxBufOffset = 0; + + StartTxRing(); + StartRxRing(); + + } else { // stop + fRunning = false; + StopTxRing(); + StopRxRing(); + fPr1State = kSTATE_READY; + } + + SetupPrimClist(); + return; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +bool Rw11CntlDEUNA::ExecGetcmd(RlinkCommandList& clist) +{ + Rw11Cpu& cpu = Cpu(); + + // FIXME_code: where is pcb read status checked ?? + if (fPC_rdpcb == 0) { // if pcb not available + fPr1Pcto = true; + return false; + } + + uint16_t func = fPcb[0] & kPC0_M_FUNC; + if (fPcb[0] & kPC0_M_MBZ) return false; + + uint32_t udbb; + uint16_t pr2len; + Wlist2UBAddrLen(&fPcb[1], udbb, pr2len); + bool udbb_ok = (udbb & ~kUBA_M) == 0; + + switch (func) { + case kFUNC_NOOP: // NOOP -------------------------- + fStats.Inc(kStatNFuncNoop); + return true; + + case kFUNC_RDPA: // RDPA -- read default mac ----- + { + fStats.Inc(kStatNFuncRdpa); + RethTools::Mac2WList(fMacDefault, &fPcb[1]); + cpu.AddWMem(clist, fPcbb+2, &fPcb[1], 3, Rw11Cpu::kCPAH_M_UBM22, true); + LogMacFunc("RDPA", fMacDefault); + return true; + } + + case kFUNC_RPA: // RPA -- read mac --------------- + { + fStats.Inc(kStatNFuncRpa); + RethTools::Mac2WList(fMacList[0], &fPcb[1]); + cpu.AddWMem(clist, fPcbb+2, &fPcb[1], 3, Rw11Cpu::kCPAH_M_UBM22, true); + LogMacFunc("RPA", fMacList[0]); + return true; + } + + case kFUNC_WPA: // WPA -- write mac--------------- + { + fStats.Inc(kStatNFuncWpa); + uint64_t mac= RethTools::WList2Mac(&fPcb[1]); + if (mac & 0x1) return false; // lsb of MAC must be 0 + fMacList[0] = mac; + LogMacFunc("RPA", fMacList[0]); + return true; + } + + case kFUNC_RMAL: // RMAL -- read mcast list ------- + { + fStats.Inc(kStatNFuncRmal); + if (!udbb_ok) return false; + uint16_t mltlen = pr2len; + if (mltlen > kDimMcast) return false; + if (mltlen == 0) return true; + uint16_t udb[3*kDimMcast]; + for (int i=0; i kDimMcast) return false; + fMcastCnt = 0; + for (int i=0; i ctrmax) ctrlen = ctrmax; + + uint16_t udb[kDimCtr]; + for (auto& w : udb) w = 0; + + Rtime dt = Rtime(CLOCK_MONOTONIC) - fCtrTimeCleared; + udb[ 0] = ctrlen; + udb[ 1] = (dt.Sec() < 0xffff) ? uint16_t(dt.Sec()) : 0xffff; + udb[ 2] = fCtrRxFra & 0xffff; + udb[ 3] = fCtrRxFra >> 16; + udb[ 4] = fCtrRxFraMcast & 0xffff; + udb[ 5] = fCtrRxFraMcast >> 16; + udb[ 8] = fCtrRxByt & 0xffff; + udb[ 9] = fCtrRxByt >> 16; + udb[10] = fCtrRxBytMcast & 0xffff; + udb[11] = fCtrRxBytMcast >> 16; + udb[12] = fCtrRxFraLoInt; + udb[13] = fCtrRxFraLoBuf; + udb[14] = fCtrTxFra & 0xffff; + udb[15] = fCtrTxFra >> 16; + udb[16] = fCtrTxFraMcast & 0xffff; + udb[17] = fCtrTxFraMcast >> 16; + udb[24] = fCtrTxByt & 0xffff; + udb[25] = fCtrTxByt >> 16; + udb[26] = fCtrTxBytMcast & 0xffff; + udb[27] = fCtrTxBytMcast >> 16; + udb[29] = fCtrTxFraAbort; + RlinkCommandList clist1; + cpu.AddWMem(clist1, udbb, udb, ctrlen, Rw11Cpu::kCPAH_M_UBM22, true); + Server().Exec(clist1); + // FIXME_code: handle access errors + if (func==kFUNC_RCCTR) ClearCtr(); + return true; + } + + case kFUNC_RMODE: // RMODE -- read mode ------------ + { + fStats.Inc(kStatNFuncRmode); + fPcb[1] = fMode; + cpu.AddWMem(clist, fPcbb+2, &fPcb[1], 1, Rw11Cpu::kCPAH_M_UBM22, true); + LogFunc("RMODE", "mode", fMode); + return true; + } + + case kFUNC_WMODE: // WMODE -- write mode ----------- + { + fStats.Inc(kStatNFuncWmode); + uint16_t mbz = fPr1Delua ? kMODE_M_MBZ_DELUA : kMODE_M_MBZ_DEUNA; + if (fPcb[1] & mbz) return false; + fMode = fPcb[1]; + LogFunc("WMODE", "mode", fMode); + return true; + } + + case kFUNC_RSTAT: // RSTAT -- read status ---------- + case kFUNC_RCSTAT: // RCSTAT -- read&clear status --- + { + fStats.Inc((func==kFUNC_RCSTAT) ? kStatNFuncRcstat : kStatNFuncRstat); + fPcb[1] = fStatus; + fPcb[2] = Rtools::Bytes2Word(kDimMcast, fMcastCnt); + fPcb[3] = fPr1Delua ? kDimCtrDelua : kDimCtrDeuna; + cpu.AddWMem(clist, fPcbb+2, &fPcb[1], 3, Rw11Cpu::kCPAH_M_UBM22, true); + LogFunc((func==kFUNC_RCSTAT) ? "RCSTAT" : "RSTAT", + "stat", fStatus, "mltlen", fMcastCnt); + if (func==kFUNC_RCSTAT) ClearStatus(); + return true; + } + + case kFUNC_RSID: // RSID -- read system ID -------- + { + fStats.Inc(kStatNFuncRsid); + if ((!udbb_ok) || pr2len != 0) return false; // pdb[2] length mbz + uint16_t pltlen = fPcb[3]; + if (pltlen &0x1) return false; // must be even + if (pltlen == 0) return true; // nothing to do... + if (pltlen > kDimPlt) return false; // PLTLEN to high is error + + uint16_t udb[kDimPlt]; + for (auto& w : udb) w = 0; + + // this follow DEUNA UG and DELUA UG (defaults are same for both) + // and the simh pdp11_xu.c implementation + udb[11] = 0x260; // type + udb[12] = 28; // ccount (+parameters... NI) + udb[13] = 7; // code + udb[14] = 0; // recnum + // mop information + udb[15] = 1; // mvtype + udb[16] = 0x0303; // mvver + mvlen + udb[17] = 0; // mvueco + mveco + // function information + udb[18] = 2; // ftype + udb[19] = 0x0502; // fval1 + flen + udb[20] = 0x0700; // hatype<07:00> + fval2 + udb[21] = 0x0600; // halen + hatype<15:08> + // built-in MAC address + RethTools::Mac2WList(fMacList[0], &udb[21]); // HA + udb[24] = 0x64; // dtype + udb[25] = (11 << 8) + 1; // dvalue + dlen + RlinkCommandList clist1; + cpu.AddWMem(clist1, udbb, udb, pltlen, Rw11Cpu::kCPAH_M_UBM22, true); + Server().Exec(clist1); + // FIXME_code: handle access errors + return true; + } + + case kFUNC_WSID: // WSID -- write system ID ------- + { + fStats.Inc(kStatNFuncWsid); + return false; // currently not implemented + } + + default: + fStats.Inc(kStatNFuncUimpl); + return false; + } + return false; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +void Rw11CntlDEUNA::SetupPrimClist() +{ + Rw11Cpu& cpu = Cpu(); + + fPrimClist.Clear(); + fPrimClist.AddAttn(); + fPC_rdpr0 = cpu.AddRibr(fPrimClist, fBase+kPR0); + fPC_rdpcb = 0; + fPC_lapcb = 0; + fPC_rdtxdsccur = 0; + fPC_latxdsccur = 0; + fPC_rdtxdscnxt = 0; + fPC_latxdscnxt = 0; + fPC_rdrxdsccur = 0; + fPC_larxdsccur = 0; + fPC_rdrxdscnxt = 0; + if (!fPcbbValid) return; + fPC_rdpcb = cpu.AddRMem(fPrimClist, fPcbb, fPcb, 4, + Rw11Cpu::kCPAH_M_UBM22, true); + fPC_lapcb = fPrimClist.AddLabo(); + if (!Running()) return; + + // Note: the memory addresses will be set before each usage with ModLalh() + // that's why the initial memory address is set as kUBA_M (end of ubmap) + fPC_rdtxdsccur = cpu.AddRMem(fPrimClist, kUBA_M, fTxDscCurPC, 3, + Rw11Cpu::kCPAH_M_UBM22, true); + fPC_latxdsccur = fPrimClist.AddLabo(); + + fPC_rdtxdscnxt = cpu.AddRMem(fPrimClist, kUBA_M, fTxDscNxtPC, 3, + Rw11Cpu::kCPAH_M_UBM22, true); + fPC_latxdscnxt = fPrimClist.AddLabo(); + + fPC_rdrxdsccur = cpu.AddRMem(fPrimClist, kUBA_M, fRxDscCurPC, 3, + Rw11Cpu::kCPAH_M_UBM22, true); + fPC_larxdsccur = fPrimClist.AddLabo(); + + fPC_rdrxdscnxt = cpu.AddRMem(fPrimClist, kUBA_M, fRxDscCurPC, 3, + Rw11Cpu::kCPAH_M_UBM22, true); + return; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs + +uint16_t Rw11CntlDEUNA::GetPr1() const +{ + uint16_t pr1 = fPr1State; + if (fPr1Pcto) pr1 |= kPR1_M_PCTO; + if (fPr1Delua) { + pr1 |= kPR1_M_DELUA; + } else { + if (!fspUnit[0]->Virt()) { + pr1 |= kPR1_M_XPWR | kPR1_M_ICAB; + } + } + return pr1; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +void Rw11CntlDEUNA::StartTxRing() +{ + RlinkCommandList clist; + uint16_t txdsccur[4]; + uint16_t txdscnxt[4]; + size_t irdtxdsccur = Cpu().AddRMem(clist, TxRingDscAddr(fTxRingIndex), + txdsccur, 3, Rw11Cpu::kCPAH_M_UBM22, true); + size_t irdtxdscnxt = Cpu().AddRMem(clist, TxRingDscAddr(TxRingIndexNext()), + txdscnxt, 3, Rw11Cpu::kCPAH_M_UBM22, true); + Server().Exec(clist); + // FIXME_code: check dsc read errors ! + StartTxRing(txdsccur, txdscnxt); + return; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +void Rw11CntlDEUNA::StartTxRing(const uint16_t dsccur[4], + const uint16_t dscnxt[4]) +{ + if (fTxRingState != kStateTxIdle) return; + + SetRingDsc(fTxDscCur, dsccur); + SetRingDsc(fTxDscNxt, dscnxt); + + if (fTxDscCurPC[2] & kTXR2_M_OWN) { // pending tx frames ? + fTxRingState = kStateTxBusy; + Server().QueueAction(boost::bind(&Rw11CntlDEUNA::TxRingHandler, + this)); + } + return; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +void Rw11CntlDEUNA::StopTxRing() +{ + fTxRingState = kStateTxIdle; + return; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +void Rw11CntlDEUNA::StartRxRing() +{ + RlinkCommandList clist; + uint16_t rxdsccur[4]; + uint16_t rxdscnxt[4]; + size_t irdrxdsccur = Cpu().AddRMem(clist, RxRingDscAddr(fRxRingIndex), + rxdsccur, 3, Rw11Cpu::kCPAH_M_UBM22, true); + size_t irdrxdscnxt = Cpu().AddRMem(clist, RxRingDscAddr(RxRingIndexNext()), + rxdscnxt, 3, Rw11Cpu::kCPAH_M_UBM22, true); + Server().Exec(clist); + // FIXME_code: check dsc read errors ! + StartRxRing(rxdsccur, rxdscnxt); + return; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +void Rw11CntlDEUNA::StartRxRing(const uint16_t dsccur[4], + const uint16_t dscnxt[4]) +{ + if (fRxRingState != kStateRxIdle) return; + + SetRingDsc(fRxDscCur, dsccur); + SetRingDsc(fRxDscNxt, dscnxt); + + if (!fRxBufQueue.empty() && // if pending rx frames + fRxDscCur[2] & kRXR2_M_OWN) { // and buffer available + fRxRingState = kStateRxBusy; + Server().QueueAction(boost::bind(&Rw11CntlDEUNA::RxRingHandler, + this)); + } + return; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +void Rw11CntlDEUNA::StopRxRing() +{ + if (fRxRingState == kStateRxPoll) fRxPollTimer.Cancel(); + fRxRingState = kStateRxIdle; + return; +} +//--------------------------------------+----------------------------------- +//! FIXME_docs +int Rw11CntlDEUNA::TxRingHandler() +{ + fTxRingState = kStateTxIdle; // expect quit + if (!Running()) return 0; // quit if not running + + RlinkCommandList clist; + Rw11Cpu& cpu = Cpu(); + Rw11UnitDEUNA& unit = *fspUnit[0]; + + if (!(fTxDscCur[2] & kTXR2_M_OWN)) return 0; // FIXME_code: shouldn't happen ! + // FIXME_code: quit if ring bad, not attached,... + + LogRingInfo('t','<'); // log initial ring dsc state + + if (fTxBufOffset == 0) { // new frame processed + fTxBuf.Clear(); // clear buffer + fTxBuf.SetTime(); // set timestamp + } + + // clear OWN+flags, keep SEGB,STF,ENF + fTxDscCur[2] &= kTXR2_M_SEGB|kTXR2_M_STF|kTXR2_M_ENF; + fTxDscCur[3] = 0; + + uint16_t stat = 0; + uint16_t pr0out = 0; + + uint16_t slen = fTxDscCur[0]; + uint32_t segb = uint32_t(fTxDscCur[1]) | uint32_t(fTxDscCur[2] & 0xff)<<16; + if (segb & ~kUBA_M) stat |= kSTAT_M_TRNG; // FIXME_code: see MBZ comment above + + uint16_t tsize = slen; + if (tsize > RethBuf::kMaxSize) { + tsize = RethBuf::kMaxSize; + fTxDscCur[3] |= kTXR3_M_BUFL; // FIXME_code: is that correct ? + } + + // read data + // FIXME_code: handle odd base !! + cpu.AddRMem(clist, segb, fTxBuf.Buf16(), (tsize+1)/2, + Rw11Cpu::kCPAH_M_UBM22, true); + Server().Exec(clist); + // FIXME_code: handle errors !! + + fTxBuf.SetSize(tsize); // FIXME_code: handle chunks ! + + clist.Clear(); + + // update current dsc + cpu.AddWMem(clist, TxRingDscAddr(fTxRingIndex)+4, &fTxDscCur[2], 2, + Rw11Cpu::kCPAH_M_UBM22, true); + clist.AddLabo(); + + // re-read next dsc; and read next-next dsc + uint16_t dsccurnew[4]; + uint16_t dscnxtnew[4]; + cpu.AddRMem(clist, TxRingDscAddr(TxRingIndexNext(1)), dsccurnew, 3, + Rw11Cpu::kCPAH_M_UBM22, true); + clist.AddLabo(); + cpu.AddRMem(clist, TxRingDscAddr(TxRingIndexNext(2)), dscnxtnew, 3, + Rw11Cpu::kCPAH_M_UBM22, true); + clist.AddLabo(); + + // signal frame done + pr0out |= kPR0_M_TXI; + cpu.AddWibr(clist, fBase+kPR0, pr0out); + + // final frame handling + fTxBuf.SetMacSource(fMacList[0]); // set source address + if (fTxBuf.Size() < RethBuf::kMinSize) { // pad if to small + ::memset(fTxBuf.Buf8()+fTxBuf.Size(), 0, RethBuf::kMinSize-fTxBuf.Size()); + fTxBuf.SetSize(RethBuf::kMinSize); + fStats.Inc(kStatNTxFraPad); + if (!(fMode&kMODE_M_TPAD)) { // runt error unless TPAD active + fTxDscCur[3] |= kTXR3_M_BUFL; + } + } + + // check for 'station match' + uint64_t macdst = fTxBuf.MacDestination(); + int matchdst = MacFilter(macdst); + if (matchdst > 0) { + fTxDscCur[2] |= kTXR2_M_MTCH; + } + + UpdateStat32(fCtrTxFra, kStatNTxFra); + UpdateStat32(fCtrTxByt, kStatNTxByt, fTxBuf.Size()); + if (fTxBuf.IsMcast()) { // Mcast includes Bcast ! + UpdateStat32(fCtrTxFraMcast, kStatNTxFraMcast); + UpdateStat32(fCtrTxBytMcast, kStatNTxBytMcast, fTxBuf.Size()); + if (fTxBuf.IsBcast()) { + fStats.Inc(kStatNTxFraBcast); + } + } + + if (fTraceLevel>2) { + RlogMsg lmsg(LogFile()); + std::ostringstream sos; + fTxBuf.Dump(sos, 4, "fTxBuf: "); + lmsg << sos.str(); + } + + LogFrameInfo('t', fTxBuf); // log transmitted frame + if (unit.Virt()) { // attached ? + RerrMsg emsg; + unit.Virt()->Snd(fTxBuf, emsg); + // FIXME_code: error handling + } + + LogRingInfo('t','>'); // log final ring dsc state + Server().Exec(clist); + // FIXME_code: handle errors + + // push ring index, update current and next dsc + fTxRingIndex = TxRingIndexNext(); + SetRingDsc(fTxDscCur, dsccurnew); + SetRingDsc(fTxDscNxt, dscnxtnew); + + // now decide whether to idle or continue + if (!(fTxDscCur[2] & kTXR2_M_OWN)) return 0; // quit if nothing to do + + fTxRingState = kStateTxBusy; // otherwise continue + return 1; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +int Rw11CntlDEUNA::RxRingHandler() +{ + fRxRingState = kStateRxIdle; + if (!Running()) return 0; // quit if not running + + RlinkCommandList clist; + Rw11Cpu& cpu = Cpu(); + + if (!(fRxDscCur[2] & kRXR2_M_OWN)) return 0; // FIXME_code: shouldn't happen ! + + if (fRxBufOffset == 0) { // new frame needed + if (fRxBufQueue.empty()) return 0; // quit if none available + fRxBufCurr = fRxBufQueue.front(); + fRxBufQueue.pop_front(); + } + RethBuf& ebuf = *fRxBufCurr; + + if (true && ebuf.Size() < RethBuf::kMinSize) { // pad if ena + ::memset(ebuf.Buf8()+ebuf.Size(), 0, RethBuf::kMinSize-ebuf.Size()); + ebuf.SetSize(RethBuf::kMinSize); + fStats.Inc(kStatNRxFraPad); + } + + LogRingInfo('r','<'); // log initial ring dsc state + LogFrameInfo('e', ebuf); // log reveived frame + + // FIXME_code: this also clears the MBZ areas !! handle this correctly + // clear OWN+flags, keep SEGB + fRxDscCur[2] &= kRXR2_M_SEGB; + fRxDscCur[3] = 0; + + uint16_t stat = 0; + uint16_t pr0out = 0; + + uint16_t slen = fRxDscCur[0]; + uint32_t segb = uint32_t(fRxDscCur[1]) | uint32_t(fRxDscCur[2] & 0xff)<<16; + if (segb & ~kUBA_M) stat |= kSTAT_M_RRNG; // FIXME_code: see MBZ comment above + + uint16_t tsize = ebuf.Size(); + + if (ebuf.Size() > slen) { + tsize = slen; + fRxDscCur[3] |= kRXR3_M_BUFL; + } + + // Note: the DEUNA returns in the rx descriptor the frame length including + // the CRC length (4 bytes) !! But apparently does not transfer the + // CRC, at least in normal mode !! See comments in simh pdp11_xu.c. + fRxDscCur[2] |= kRXR2_M_STF | kRXR2_M_ENF; + fRxDscCur[3] |= tsize+RethBuf::kCrcSize; + + // write data + cpu.AddWMem(clist, segb, ebuf.Buf16(), (tsize+1)/2, + Rw11Cpu::kCPAH_M_UBM22, true); + clist.AddLabo(); + // update current dsc + cpu.AddWMem(clist, RxRingDscAddr(fRxRingIndex)+4, &fRxDscCur[2], 2, + Rw11Cpu::kCPAH_M_UBM22, true); + clist.AddLabo(); + + // re-read next dsc; and read next-next dsc + uint16_t dsccurnew[4]; + uint16_t dscnxtnew[4]; + cpu.AddRMem(clist, RxRingDscAddr(RxRingIndexNext(1)), dsccurnew, 3, + Rw11Cpu::kCPAH_M_UBM22, true); + clist.AddLabo(); + cpu.AddRMem(clist, RxRingDscAddr(RxRingIndexNext(2)), dscnxtnew, 3, + Rw11Cpu::kCPAH_M_UBM22, true); + clist.AddLabo(); + + // signal frame done + pr0out |= kPR0_M_RXI; + cpu.AddWibr(clist, fBase+kPR0, pr0out); + + UpdateStat32(fCtrRxFra, kStatNRxFra); + UpdateStat32(fCtrRxByt, kStatNRxByt, ebuf.Size()); + if (ebuf.IsMcast()) { // Mcast includes Bcast ! + UpdateStat32(fCtrRxFraMcast, kStatNRxFraMcast); + UpdateStat32(fCtrRxBytMcast, kStatNRxBytMcast, ebuf.Size()); + if (ebuf.IsBcast()) { + fStats.Inc(kStatNRxFraBcast); + } + } + + LogRingInfo('r','>'); // log final ring dsc state + Server().Exec(clist); + // FIXME_code: handle errors + + // push ring index, update current and next dsc + fRxRingIndex = RxRingIndexNext(); + SetRingDsc(fRxDscCur, dsccurnew); + SetRingDsc(fRxDscNxt, dscnxtnew); + + // now decide whether to idle, continue, or poll + if (fRxBufQueue.empty()) return 0; // quit if nothing to do + if (!(fRxDscCur[2] & kRXR2_M_OWN)) { // no free buffer + fRxPollTimer.SetRelative(fRxPollTime); + fRxRingState = kStateRxPoll; // activate timer + return 0; + } + + fRxRingState = kStateRxBusy; // otherwise continue + return 1; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +int Rw11CntlDEUNA::RxPollHandler(const pollfd& pfd) +{ + // bail-out and cancel handler if poll returns an error event + if (pfd.revents & (~pfd.events)) return -1; + + uint64_t cnt = fRxPollTimer.Read(); // harvest expiration count + if (!Running() || // if not running + fRxRingState != kStateRxPoll || // if not polling + !cnt) return 0; // if not expired -> quit + + fRxRingState = kStateRxIdle; // end poll + StartRxRing(); // re-start rx ring + + return 0; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +int Rw11CntlDEUNA::MacFilter(uint64_t mac) +{ + int maxind = 2 + fMcastCnt; + for (int i=0; i 0xffff) stat = 0xffff; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11CntlDEUNA::UpdateStat32(uint32_t& stat, size_t ind, uint32_t inc) +{ + fStats.Inc(ind, inc); + stat += inc; + if (stat < inc) stat = 0xffffffff; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +void Rw11CntlDEUNA::LogMacFunc(const char* cmd, uint64_t mac) +{ + if (fTraceLevel == 0) return; + RlogMsg lmsg(LogFile()); + lmsg << "-I " << Name() << ": " << cmd << ": " << RethTools::Mac2String(mac); + return; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +void Rw11CntlDEUNA::LogMcastFunc(const char* cmd) +{ + if (fTraceLevel == 0) return; + RlogMsg lmsg(LogFile()); + lmsg << "-I " << Name() << ": " << cmd << ": mltlen=" << fMcastCnt; + for (int i=0; i>8), 2, 8) + << "," << RosPrintBvi(uint16_t(dsc[3]>>12), 2, 4) << ": "; + + sos << RingDsc2OSEString(dsc); + + if (dsc[2] & kTXR2_M_ERRS) sos << " errs"; + if (rxtx == 't') { + if (dsc[2] & kTXR2_M_MTCH) sos << " mtch"; + if (dsc[2] & kTXR2_M_MORE) sos << " more"; + if (dsc[2] & kTXR2_M_ONE) sos << " one"; + if (dsc[2] & kTXR2_M_DEF) sos << " def"; + sos << ","; + if (dsc[2] & kTXR3_M_BUFL) sos << " bufl"; + if (dsc[2] & kTXR3_M_UBTO) sos << " ubto"; + if (dsc[2] & kTXR3_M_LCOL) sos << " lcol"; + if (dsc[2] & kTXR3_M_LCAR) sos << " lcar"; + if (dsc[2] & kTXR3_M_RTRY) sos << " rtry"; + } else { + if (dsc[2] & kRXR2_M_FRAM) sos << " fram"; + if (dsc[2] & kRXR2_M_OFLO) sos << " oflo"; + if (dsc[2] & kRXR2_M_CRC) sos << " crc"; + sos << ","; + if (dsc[2] & kRXR3_M_BUFL) sos << " bufl"; + if (dsc[2] & kRXR3_M_UBTO) sos << " ubto"; + if (dsc[2] & kRXR3_M_NCHN) sos << " nchn"; + if (dsc[2] & kRXR3_M_OVRN) sos << " ovrn"; + } + + return sos.str(); +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs + +std::string Rw11CntlDEUNA::RingDsc2OSEString(const uint16_t dsc[4], char fill) +{ + char res[4] = {fill,fill,fill,0}; + if (dsc[2] & kTXR2_M_OWN) res[0] = 'O'; + if (dsc[2] & kTXR2_M_STF) res[1] = 'S'; + if (dsc[2] & kTXR2_M_ENF) res[2] = 'E'; + return string(res); +} + +} // end namespace Retro diff --git a/tools/src/librw11/Rw11CntlDEUNA.hpp b/tools/src/librw11/Rw11CntlDEUNA.hpp new file mode 100644 index 00000000..e89fa55b --- /dev/null +++ b/tools/src/librw11/Rw11CntlDEUNA.hpp @@ -0,0 +1,413 @@ +// $Id: Rw11CntlDEUNA.hpp 875 2017-04-15 21:58:50Z mueller $ +// +// Copyright 2014-2017 by Walter F.J. Mueller +// +// 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 +// 2017-04-14 875 1.0 Initial version +// 2014-06-09 561 0.1 First draft +// --------------------------------------------------------------------------- + + +/*! + \file + \version $Id: Rw11CntlDEUNA.hpp 875 2017-04-15 21:58:50Z mueller $ + \brief Declaration of class Rw11CntlDEUNA. +*/ + +#ifndef included_Retro_Rw11CntlDEUNA +#define included_Retro_Rw11CntlDEUNA 1 + +#include + +#include "librtools/Rtime.hpp" +#include "librlink/RtimerFd.hpp" + +#include "RethBuf.hpp" + +#include "Rw11CntlBase.hpp" +#include "Rw11UnitDEUNA.hpp" + +namespace Retro { + + class Rw11CntlDEUNA : public Rw11CntlBase { + public: + + Rw11CntlDEUNA(); + ~Rw11CntlDEUNA(); + + void Config(const std::string& name, uint16_t base, int lam); + + virtual void Start(); + + virtual void UnitSetup(size_t ind); + + void SetType(const std::string& type); + void SetMacDefault(const std::string& mac); + void SetRxPollTime(const Rtime& time); + void SetRxQueLimit(size_t rxqlim); + + std::string MacDefault() const; + const Rtime& RxPollTime() const; + size_t RxQueLimit() const; + + bool Running() const; + + const char* MnemoPcmd(uint16_t pcmd) const; + const char* MnemoFunc(uint16_t func) const; + const char* MnemoState(uint16_t state) const; + + bool RcvCallback(RethBuf::pbuf_t& pbuf); + + virtual void Dump(std::ostream& os, int ind=0, const char* text=0, + int detail=0) const; + + // some constants (also defined in cpp) + static const uint16_t kIbaddr = 0174510; //!< DEUNA default address + static const int kLam = 9; //!< DEUNA default lam + + static const uint16_t kPR0 = 000; //!< PR0 reg offset + static const uint16_t kPR1 = 002; //!< PR1 reg offset + static const uint16_t kPR2 = 004; //!< PR2 reg offset + static const uint16_t kPR3 = 006; //!< PR3 reg offset + + static const uint16_t kProbeOff = kPR0; //!< probe address offset (pr0) + static const bool kProbeInt = true; //!< probe int active + static const bool kProbeRem = true; //!< probr rem active + + static const uint16_t kPR0_M_SERI = kWBit15; //!< SERI: status error intr + static const uint16_t kPR0_M_PCEI = kWBit14; //!< PCEI: port cmd err intr + static const uint16_t kPR0_M_RXI = kWBit13; //!< RXI: receive rung intr + static const uint16_t kPR0_M_TXI = kWBit12; //!< TXI: transmit rung intr + static const uint16_t kPR0_M_DNI = kWBit11; //!< DNI: done intr + static const uint16_t kPR0_M_RCBI = kWBit10; //!< RCBI: rcv buff unavail + static const uint16_t kPR0_M_BUSY = kWBit09; //!< BUSY: command busy + static const uint16_t kPR0_M_USCI = kWBit08; //!< USCI: unsol state chang + static const uint16_t kPR0_M_INTR = kWBit07; //!< INTR: intr summary + static const uint16_t kPR0_M_INTE = kWBit06; //!< INTE: intr enable + static const uint16_t kPR0_M_RSET = kWBit05; //!< RSET: sw reset + static const uint16_t kPR0_M_BRST = kWBit04; //!< RSET: breset seen + static const uint16_t kPR0_M_PCMD = 00017; //!< PCMD: port command + + static const uint16_t kPR0_V_PCMDBP= 12; //!< PCMDBP: port busy prot + static const uint16_t kPR0_B_PCMDBP= 00017; //!< PCMDBP: port busy prot + static const uint16_t kPR0_M_PCWWB = kWBit08; //!< PCWWB: pcmd write w busy + + static const uint16_t kPCMD_NOOP = 0; //!< NOOP: noop + static const uint16_t kPCMD_GETPCBB = 1; //!< GETPCBB: get pcb base + static const uint16_t kPCMD_GETCMD = 2; //!< GETCMD: get command + static const uint16_t kPCMD_SELFTST = 3; //!< SELFTST: self test + static const uint16_t kPCMD_START = 4; //!< START: start tx/rx + static const uint16_t kPCMD_BOOT = 5; //!< BOOT: boot + static const uint16_t kPCMD_PDMD = 010; //!< PDMD: poll demand + static const uint16_t kPCMD_HALT = 016; //!< HALT: halt + static const uint16_t kPCMD_STOP = 017; //!< STOP: stop + + static const uint16_t kPR1_M_XPWR = kWBit15; //!< XPWR: transceive pwr fail + static const uint16_t kPR1_M_ICAB = kWBit14; //!< ICAB: cable fail + static const uint16_t kPR1_M_PCTO = kWBit07; //!< PCTO: port cmd timeout + static const uint16_t kPR1_M_DELUA= kWBit04; //!< ID0: 1=DELUA;0=DEUNA + static const uint16_t kPR1_M_STATE= 0017; //!< STATE: port status + + static const uint16_t kSTATE_RESET = 0; //!< reset + static const uint16_t kSTATE_PLOAD = 1; //!< primary load + static const uint16_t kSTATE_READY = 2; //!< ready + static const uint16_t kSTATE_RUN = 3; //!< running + static const uint16_t kSTATE_UHALT = 5; //!< unibus halted + static const uint16_t kSTATE_NHALT = 6; //!< ni halted + static const uint16_t kSTATE_NUHALT = 7; //!< ni and unibus halted + static const uint16_t kSTATE_PHALT = 010; //!< port halted + static const uint16_t kSTATE_SLOAD = 017; //!< secondary load + + static const uint16_t kPC0_M_FUNC = 0x00ff; //!< FUNC: function code + static const uint16_t kPC0_M_MBZ = 0xff00; //!< MBZ + + static const uint16_t kFUNC_NOOP = 0; //!< NOOP: noop + static const uint16_t kFUNC_RDPA = 2; //!< RDPA: read def MAC + static const uint16_t kFUNC_RPA = 4; //!< RPA: read phys MAC + static const uint16_t kFUNC_WPA = 5; //!< WPA: write phys MAC + static const uint16_t kFUNC_RMAL = 6; //!< RMAL: read mcast MAC list + static const uint16_t kFUNC_WMAL = 7; //!< RMAL: write mcast MAC list + static const uint16_t kFUNC_RRF = 010; //!< RRF: read ring format + static const uint16_t kFUNC_WRF = 011; //!< WRF: write ring format + static const uint16_t kFUNC_RCTR = 012; //!< RCTR: read counters + static const uint16_t kFUNC_RCCTR = 013; //!< RCCTR: read&clr counters + static const uint16_t kFUNC_RMODE = 014; //!< RMODE: read mode + static const uint16_t kFUNC_WMODE = 015; //!< WMODE: write write + static const uint16_t kFUNC_RSTAT = 016; //!< RSTAT: read status + static const uint16_t kFUNC_RCSTAT = 017; //!< RCSTAT: read&clr status + static const uint16_t kFUNC_RSID = 022; //!< RSID: read system id + static const uint16_t kFUNC_WSID = 023; //!< WSID: write system id + + static const uint16_t kSTAT_M_ERRS = kWBit15;//!< ERRS: error summary + static const uint16_t kSTAT_M_MERR = kWBit14;//!< MERR: multiple errors + static const uint16_t kSTAT_M_BABL = kWBit13;//!< BABL: xmit on long(DELUA) + static const uint16_t kSTAT_M_CERR = kWBit12;//!< CERR: collision test er + static const uint16_t kSTAT_M_TMOT = kWBit11;//!< TMOT: UNIBUS timeout + static const uint16_t kSTAT_M_RRNG = kWBit09;//!< RRNG: rx ring error + static const uint16_t kSTAT_M_TRNG = kWBit08;//!< TRNG: tx ring error + static const uint16_t kSTAT_M_PTCH = kWBit07;//!< PTCH: ROM patch + static const uint16_t kSTAT_M_RRAM = kWBit06;//!< RRAM: run from RAM + static const uint16_t kSTAT_M_RREV = 077; //!< RREV: ROM version + + static const uint16_t kMODE_M_PROM = kWBit15;//!< PROM: promiscous mode + static const uint16_t kMODE_M_ENAL = kWBit14;//!< ENAL: ena all mcasts + static const uint16_t kMODE_M_DRDC = kWBit13;//!< DRDC: dis data chaining + static const uint16_t kMODE_M_TPAD = kWBit12;//!< TPAD: tx msg padding ena + static const uint16_t kMODE_M_ECT = kWBit11;//!< ECT: ena collision test + static const uint16_t kMODE_M_DMNT = kWBit09;//!< DMNT: dis maint message + static const uint16_t kMODE_M_INTL = kWBit06;//!< INTL: int loopback(DELUA) + static const uint16_t kMODE_M_DTCR = kWBit03;//!< DTCR: dis tx CRC + static const uint16_t kMODE_M_LOOP = kWBit02;//!< LOOP: int loopback + static const uint16_t kMODE_M_HDPX = kWBit00;//!< HDPX: half-duplex (DEUNA) + static const uint16_t kMODE_M_MBZ_DEUNA = 0x05f2; //!< MBZ bit:10,8:4,1 + static const uint16_t kMODE_M_MBZ_DELUA = 0x05b2; //!< MBZ bit:10,8:7,5:4,1 + + static const uint16_t kTXR2_M_OWN = kWBit15; //!< OWN: owned by DEUNA + static const uint16_t kTXR2_M_ERRS = kWBit14; //!< ERRS: error summary + static const uint16_t kTXR2_M_MTCH = kWBit13; //!< MTCH: station match + static const uint16_t kTXR2_M_MORE = kWBit12; //!< MORE: mult retry needed + static const uint16_t kTXR2_M_ONE = kWBit11; //!< ONE: one collision + static const uint16_t kTXR2_M_DEF = kWBit10; //!< DEF: deferred + static const uint16_t kTXR2_M_STF = kWBit09; //!< STF: start of frame + static const uint16_t kTXR2_M_ENF = kWBit08; //!< ENF: end of frame + static const uint16_t kTXR2_M_SEGB = 00003; //!< SEGB: msg of seg base + static const uint16_t kTXR3_M_BUFL = kWBit15; //!< BUFL: buf length error + static const uint16_t kTXR3_M_UBTO = kWBit14; //!< UBTO: UNIBUS timeout + static const uint16_t kTXR3_M_UFLO = kWBit13; //!< UFLO: UNIBUS underflow + static const uint16_t kTXR3_M_LCOL = kWBit12; //!< LCOL: late collision + static const uint16_t kTXR3_M_LCAR = kWBit11; //!< LCAR: lost carrier + static const uint16_t kTXR3_M_RTRY = kWBit10; //!< RTRY: retry failure + static const uint16_t kTXR3_M_TDR = 01777; //!< TDR: TDR value if RTRY=1 + + static const uint16_t kRXR2_M_OWN = kWBit15; //!< OWN: owned by DENUA + static const uint16_t kRXR2_M_ERRS = kWBit14; //!< ERRS: error summary + static const uint16_t kRXR2_M_FRAM = kWBit13; //!< FRAM: frame error + static const uint16_t kRXR2_M_OFLO = kWBit12; //!< OFLO: message overflow + static const uint16_t kRXR2_M_CRC = kWBit11; //!< CRC: CRC check error + static const uint16_t kRXR2_M_STF = kWBit09; //!< STF: start of frame + static const uint16_t kRXR2_M_ENF = kWBit08; //!< ENF: end of frame + static const uint16_t kRXR2_M_SEGB = 000003; //!< SEGB: msg of seg base + static const uint16_t kRXR3_M_BUFL = kWBit15; //!< BUFL: buf length error + static const uint16_t kRXR3_M_UBTO = kWBit14; //!< UBTO: UNIBUS timeout + static const uint16_t kRXR3_M_NCHN = kWBit13; //!< NCHN: no data chaining + static const uint16_t kRXR3_M_OVRN = kWBit12; //!< OVRN: overrun error + static const uint16_t kRXR3_M_MLEN = 07777; //!< MLEN: message length + + static const uint32_t kUBA_M = 0x3fffe; //!< bits of even unibus address + static const uint32_t kUBAODD_M = 0x3ffff; //!< bits of odd unibus address + static const uint16_t kDimMcast = 10; //!< max length Mcast list (MAXMLT) + static const uint16_t kDimCtrDeuna = 32; //!< DEUNA count words (MAXCTR) + static const uint16_t kDimCtrDelua = 34; //!< DELUA count words (MAXCTR) + static const uint16_t kDimCtr = 34; //!< max MAXCTR + static const uint16_t kDimPlt = 100; //!< max MAXPLT + + // statistics counter indices + enum stats { + kStatNPcmdNoop = Rw11Cntl::kDimStat, + kStatNPcmdGetpcbb, + kStatNPcmdGetcmd, + kStatNPcmdSelftst, + kStatNPcmdStart, + kStatNPcmdPdmd, + kStatNPcmdStop, + kStatNPcmdHalt, + kStatNPcmdRsrvd, + kStatNPcmdUimpl, + kStatNFuncNoop, + kStatNFuncRdpa, + kStatNFuncRpa, + kStatNFuncWpa, + kStatNFuncRmal, + kStatNFuncWmal, + kStatNFuncRrf, + kStatNFuncWrf, + kStatNFuncRctr, + kStatNFuncRcctr, + kStatNFuncRmode, + kStatNFuncWmode, + kStatNFuncRstat, + kStatNFuncRcstat, + kStatNFuncRsid, + kStatNFuncWsid, + kStatNFuncUimpl, + kStatNRxFraSeen, + kStatNRxFraFDst, + kStatNRxFraFBcast, + kStatNRxFraFMcast, + kStatNRxFraFProm, + kStatNRxFraFUDrop, + kStatNRxFraFMDrop, + kStatNRxFraQLDrop, + kStatNRxFraNRDrop, + kStatNRxFra, + kStatNRxFraMcast, + kStatNRxFraBcast, + kStatNRxByt, + kStatNRxBytMcast, + kStatNRxFraLoInt, + kStatNRxFraLoBuf, + kStatNRxFraPad, + kStatNTxFra, + kStatNTxFraMcast, + kStatNTxFraBcast, + kStatNTxByt, + kStatNTxBytMcast, + kStatNTxFraAbort, + kStatNTxFraPad, + kStatNFraLoop, + kDimStat + }; + + protected: + + enum s_tx { + kStateTxIdle = 0, + kStateTxBusy + }; + enum s_rx { + kStateRxIdle = 0, + kStateRxBusy, + kStateRxPoll + }; + + int AttnHandler(RlinkServer::AttnArgs& args); + + void ClearMacList(); + void ClearCtr(); + void ClearStatus(); + + void Reset(); + void SetRunning(bool run); + bool ExecGetcmd(RlinkCommandList& clist); + + void Wlist2UBAddr(const uint16_t wlist[2], uint32_t& addr); + void Wlist2UBAddrLen(const uint16_t wlist[2], + uint32_t& addr, uint16_t& len); + void UBAddrLen2Wlist(uint16_t wlist[2], + uint32_t addr, uint16_t len); + void SetupPrimClist(); + + uint16_t GetPr1() const; + + void StartTxRing(); + void StartTxRing(const uint16_t dsccur[4], + const uint16_t dscnxt[4]); + void StopTxRing(); + + void StartRxRing(); + void StartRxRing(const uint16_t dsccur[4], + const uint16_t dscnxt[4]); + void StopRxRing(); + + int TxRingHandler(); + int RxRingHandler(); + int RxPollHandler(const pollfd& pfd); + + uint16_t RingIndexNext(uint16_t index, uint16_t size, + uint16_t inc=1) const; + uint16_t TxRingIndexNext(uint16_t inc=1) const; + uint16_t RxRingIndexNext(uint16_t inc=1) const; + + uint32_t RingDscAddr(uint32_t base, uint16_t elen, + uint16_t index) const; + uint32_t TxRingDscAddr(uint16_t index) const; + uint32_t RxRingDscAddr(uint16_t index) const; + + int MacFilter(uint64_t mac); + + void UpdateStat16(uint32_t& stat, size_t ind, uint32_t inc=1); + void UpdateStat32(uint32_t& stat, size_t ind, uint32_t inc=1); + + void LogMacFunc(const char* cmd, uint64_t mac); + void LogMcastFunc(const char* cmd); + void LogRingFunc(const char* cmd); + void LogFunc(const char* cmd, const char* tag1, uint16_t val1, + const char* tag2=nullptr, uint16_t val2=0); + void LogRingInfo(char rxtx, char rw); + void LogFrameInfo(char rxtx, const RethBuf& buf); + + static void SetRingDsc(uint16_t dst[4], const uint16_t src[4]); + static std::string RingDsc2String(const uint16_t dsc[4], char rxtx); + static std::string RingDsc2OSEString(const uint16_t dsc[4], char fill=' '); + + protected: + size_t fPC_rdpr0; //!< PrimClist: rd pr0 index + size_t fPC_rdpcb; //!< PrimClist: rd pcb index + size_t fPC_lapcb; //!< PrimClist: la pcb index + size_t fPC_rdtxdsccur; //!< PrimClist: rd txdsc cur index + size_t fPC_latxdsccur; //!< PrimClist: la txdsc cur index + size_t fPC_rdtxdscnxt; //!< PrimClist: rd txdsc nxt index + size_t fPC_latxdscnxt; //!< PrimClist: la txdsc nxt index + size_t fPC_rdrxdsccur; //!< PrimClist: rd rxdsc index + size_t fPC_larxdsccur; //!< PrimClist: la rxdsc index + size_t fPC_rdrxdscnxt; //!< PrimClist: rd rxdsc index + bool fPcbbValid; //!< pcbb valid + uint32_t fPcbb; //!< process control block base + uint16_t fPcb[4]; //!< process control block + bool fRingValid; //!< ring format valid + uint32_t fTxRingBase; //!< tx ring base + uint16_t fTxRingSize; //!< tx ring size (# of entries) + uint16_t fTxRingELen; //!< tx ring entry length + uint32_t fRxRingBase; //!< rx ring base + uint16_t fRxRingSize; //!< rx ring size (# of entries) + uint16_t fRxRingELen; //!< rx ring entry length + uint64_t fMacDefault; //!< default MAC + uint64_t fMacList[2+kDimMcast]; //!< MAC list:0=phys,1=bcast,2+=mcast + int fMcastCnt; //!< mcast count + uint16_t fPr0Last; //!< last pr0 value + bool fPr1Pcto; //!< pr1 pcto flag + bool fPr1Delua; //!< pr1 delua flag + uint16_t fPr1State; //!< pr1 state + bool fRunning; //!< in kSTATE_RUN and active + uint16_t fMode; //!< mode + uint16_t fStatus; //!< status + uint16_t fTxRingIndex; //!< tx ring index + uint16_t fRxRingIndex; //!< rx ring index + uint16_t fTxDscCurPC[4]; //!< tx cur ring dsc from PrimClist + uint16_t fTxDscNxtPC[4]; //!< tx nxt ring dsc from PrimClist + uint16_t fRxDscCurPC[4]; //!< rx cur ring dsc from PrimClist + uint16_t fRxDscNxtPC[4]; //!< rx nxt ring dsc from PrimClist + enum s_tx fTxRingState; //!< tx ring handler state + uint16_t fTxDscCur[4]; //!< tx cur ring dsc + uint16_t fTxDscNxt[4]; //!< tx nxt ring dsc + RethBuf fTxBuf; //!< tx packet buffer + size_t fTxBufOffset; //!< tx packet offset + enum s_rx fRxRingState; //!< rx ring handler busy + uint16_t fRxDscCur[4]; //!< rx cur ring dsc + uint16_t fRxDscNxt[4]; //!< rx nxt ring dsc + Rtime fRxPollTime; //!< rx poll time interval + size_t fRxQueLimit; //!< rx queue limit + RtimerFd fRxPollTimer; //!< rx poll timer + std::deque fRxBufQueue; //!< rx packet queue + RethBuf::pbuf_t fRxBufCurr; //!< rx packet current + size_t fRxBufOffset; //!< rx packet offset + Rtime fCtrTimeCleared; //!< ctr: time when cleared + uint32_t fCtrRxFra; //!< ctr: rcvd frames + uint32_t fCtrRxFraMcast; //!< ctr: rcvd mcast frames + uint32_t fCtrRxByt; //!< ctr: rcvd bytes + uint32_t fCtrRxBytMcast; //!< ctr: rcvd mcast bytes + uint32_t fCtrRxFraLoInt; //!< ctr: rcvd frame lost int error + uint32_t fCtrRxFraLoBuf; //!< ctr: rcvd frame lost buffers + uint32_t fCtrTxFra; //!< ctr: xmit frames + uint32_t fCtrTxFraMcast; //!< ctr: xmit mcast frames + uint32_t fCtrTxByt; //!< ctr: xmit bytes + uint32_t fCtrTxBytMcast; //!< ctr: xmit mcast bytes + uint32_t fCtrTxFraAbort; //!< ctr: xmit aborted frames + uint32_t fCtrFraLoop; //!< ctr: loopback frames + }; + +} // end namespace Retro + +#include "Rw11CntlDEUNA.ipp" + +#endif diff --git a/tools/src/librw11/Rw11CntlDEUNA.ipp b/tools/src/librw11/Rw11CntlDEUNA.ipp new file mode 100644 index 00000000..92bf9e01 --- /dev/null +++ b/tools/src/librw11/Rw11CntlDEUNA.ipp @@ -0,0 +1,134 @@ +// $Id: Rw11CntlDEUNA.ipp 858 2017-03-05 17:41:37Z mueller $ +// +// Copyright 2017- by Walter F.J. Mueller +// +// 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 +// 2017-02-25 856 1.0 Initial version +// --------------------------------------------------------------------------- + +/*! + \file + \version $Id: Rw11CntlDEUNA.ipp 858 2017-03-05 17:41:37Z mueller $ + \brief Implemenation (inline) of Rw11CntlDEUNA. +*/ + +// all method definitions in namespace Retro +namespace Retro { + +//--------------------------------------+----------------------------------- +//! FIXME_docs +inline const Rtime& Rw11CntlDEUNA::RxPollTime() const +{ + return fRxPollTime; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +inline size_t Rw11CntlDEUNA::RxQueLimit() const +{ + return fRxQueLimit; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +inline bool Rw11CntlDEUNA::Running() const +{ + return fRunning; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +inline void Rw11CntlDEUNA::Wlist2UBAddr(const uint16_t wlist[2], uint32_t& addr) +{ + addr = uint32_t(wlist[0]) | uint32_t(wlist[1])<<16; + return; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +inline void Rw11CntlDEUNA::Wlist2UBAddrLen(const uint16_t wlist[2], + uint32_t& addr, uint16_t& len) +{ + addr = uint32_t(wlist[0]) | uint32_t(wlist[1] & 0xff)<<16; + len = (wlist[1]>>8) & 0xff; + return; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +inline void Rw11CntlDEUNA::UBAddrLen2Wlist(uint16_t wlist[2], + uint32_t addr, uint16_t len) +{ + wlist[0] = uint16_t(addr); + wlist[1] = uint16_t(addr>>16) | ((len & 0xff)<<8); + return; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +inline uint16_t Rw11CntlDEUNA::RingIndexNext(uint16_t index, uint16_t size, + uint16_t inc) const +{ + uint16_t next = index + inc; + if (next >= size) next -= size; + return next; +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +inline uint16_t Rw11CntlDEUNA::TxRingIndexNext(uint16_t inc) const +{ + return RingIndexNext(fTxRingIndex, fTxRingSize, inc); +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +inline uint16_t Rw11CntlDEUNA::RxRingIndexNext(uint16_t inc) const +{ + return RingIndexNext(fRxRingIndex, fRxRingSize, inc); +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +inline uint32_t Rw11CntlDEUNA::RingDscAddr(uint32_t base, uint16_t elen, + uint16_t index) const +{ + return base + 2 * uint32_t(elen) * uint32_t(index); +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +inline uint32_t Rw11CntlDEUNA::TxRingDscAddr(uint16_t index) const +{ + return fTxRingBase + 2 * uint32_t(fTxRingELen) * uint32_t(index); +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +inline uint32_t Rw11CntlDEUNA::RxRingDscAddr(uint16_t index) const +{ + return fRxRingBase + 2 * uint32_t(fRxRingELen) * uint32_t(index); +} + +//--------------------------------------+----------------------------------- +//! FIXME_docs +inline void Rw11CntlDEUNA::SetRingDsc(uint16_t dst[4], const uint16_t src[4]) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + return; +} + +} // end namespace Retro diff --git a/tools/src/librw11/Rw11UnitDEUNA.cpp b/tools/src/librw11/Rw11UnitDEUNA.cpp new file mode 100644 index 00000000..1b6a0dac --- /dev/null +++ b/tools/src/librw11/Rw11UnitDEUNA.cpp @@ -0,0 +1,90 @@ +// $Id: Rw11UnitDEUNA.cpp 868 2017-04-07 20:09:33Z mueller $ +// +// Copyright 2014-2017 by Walter F.J. Mueller +// +// 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 +// 2017-01-29 847 1.0 Initial version +// 2014-06-09 561 0.1 First draft +// --------------------------------------------------------------------------- + +/*! + \file + \version $Id: Rw11UnitDEUNA.cpp 868 2017-04-07 20:09:33Z mueller $ + \brief Implemenation of Rw11UnitDEUNA. +*/ + +#include "boost/bind.hpp" + +#include "librtools/RosFill.hpp" +#include "Rw11CntlDEUNA.hpp" + +#include "Rw11UnitDEUNA.hpp" + +using namespace std; + +/*! + \class Retro::Rw11UnitDEUNA + \brief FIXME_docs +*/ + +// all method definitions in namespace Retro +namespace Retro { + +//------------------------------------------+----------------------------------- +//! Constructor + +Rw11UnitDEUNA::Rw11UnitDEUNA(Rw11CntlDEUNA* pcntl, size_t index) + : Rw11UnitVirt(pcntl, index), + fpCntl(pcntl) +{} + +//------------------------------------------+----------------------------------- +//! Destructor + +Rw11UnitDEUNA::~Rw11UnitDEUNA() +{} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11UnitDEUNA::Dump(std::ostream& os, int ind, const char* text, + int detail) const +{ + RosFill bl(ind); + os << bl << (text?text:"--") << "Rw11UnitDEUNA @ " << this << endl; + os << bl << " fpCntl: " << fpCntl << std::endl; + Rw11UnitVirt::Dump(os, ind, " ^", detail); + return; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11UnitDEUNA::AttachDone() +{ + fpVirt->SetupRcvCallback(boost::bind(&Rw11CntlDEUNA::RcvCallback, + &Cntl(), _1)); + Cntl().UnitSetup(0); + return; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11UnitDEUNA::DetachDone() +{ + Cntl().UnitSetup(0); + return; +} + +} // end namespace Retro diff --git a/tools/src/librw11/Rw11UnitDEUNA.hpp b/tools/src/librw11/Rw11UnitDEUNA.hpp new file mode 100644 index 00000000..9546797e --- /dev/null +++ b/tools/src/librw11/Rw11UnitDEUNA.hpp @@ -0,0 +1,61 @@ +// $Id: Rw11UnitDEUNA.hpp 868 2017-04-07 20:09:33Z mueller $ +// +// Copyright 2014-2017 by Walter F.J. Mueller +// +// 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 +// 2017-01-29 847 1.0 Initial version +// 2014-06-09 561 0.1 First draft +// --------------------------------------------------------------------------- + + +/*! + \file + \version $Id: Rw11UnitDEUNA.hpp 868 2017-04-07 20:09:33Z mueller $ + \brief Declaration of class Rw11UnitDEUNA. +*/ + +#ifndef included_Retro_Rw11UnitDEUNA +#define included_Retro_Rw11UnitDEUNA 1 + +#include "Rw11VirtEth.hpp" + +#include "Rw11UnitVirt.hpp" + +namespace Retro { + + class Rw11CntlDEUNA; // forw decl to avoid circular incl + + class Rw11UnitDEUNA : public Rw11UnitVirt { + public: + Rw11UnitDEUNA(Rw11CntlDEUNA* pcntl, size_t index); + ~Rw11UnitDEUNA(); + + Rw11CntlDEUNA& Cntl() const; + + virtual void Dump(std::ostream& os, int ind=0, const char* text=0, + int detail=0) const; + + protected: + virtual void AttachDone(); + virtual void DetachDone(); + + protected: + Rw11CntlDEUNA* fpCntl; + + }; + +} // end namespace Retro + +#include "Rw11UnitDEUNA.ipp" + +#endif diff --git a/tools/src/librw11/Rw11UnitDEUNA.ipp b/tools/src/librw11/Rw11UnitDEUNA.ipp new file mode 100644 index 00000000..ca68a33a --- /dev/null +++ b/tools/src/librw11/Rw11UnitDEUNA.ipp @@ -0,0 +1,44 @@ +// $Id: Rw11UnitDEUNA.ipp 858 2017-03-05 17:41:37Z mueller $ +// +// Copyright 2014-2017 by Walter F.J. Mueller +// +// 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 +// 2017-01-29 847 1.0 Initial version +// 2014-06-09 561 0.1 First draft +// --------------------------------------------------------------------------- + +/*! + \file + \version $Id: Rw11UnitDEUNA.ipp 858 2017-03-05 17:41:37Z mueller $ + \brief Implemenation (inline) of Rw11UnitDEUNA. +*/ + +#include "Rw11UnitDEUNA.hpp" + +/*! + \class Retro::Rw11UnitDEUNA + \brief FIXME_docs +*/ + +// all method definitions in namespace Retro +namespace Retro { + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +inline Rw11CntlDEUNA& Rw11UnitDEUNA::Cntl() const +{ + return *fpCntl; +} + +} // end namespace Retro diff --git a/tools/src/librwxxtpp/Makefile b/tools/src/librwxxtpp/Makefile index de0b54e1..52ab0700 100644 --- a/tools/src/librwxxtpp/Makefile +++ b/tools/src/librwxxtpp/Makefile @@ -40,6 +40,7 @@ OBJ_all += RtclRw11CntlRK11.o RtclRw11UnitRK11.o OBJ_all += RtclRw11CntlRL11.o RtclRw11UnitRL11.o OBJ_all += RtclRw11CntlRHRP.o RtclRw11UnitRHRP.o OBJ_all += RtclRw11CntlTM11.o RtclRw11UnitTM11.o +OBJ_all += RtclRw11CntlDEUNA.o RtclRw11UnitDEUNA.o OBJ_all += RtclRw11Virt.o OBJ_all += RtclRw11VirtFactory.o OBJ_all += RtclRw11VirtDiskOver.o diff --git a/tools/src/librwxxtpp/RtclRw11CntlDEUNA.cpp b/tools/src/librwxxtpp/RtclRw11CntlDEUNA.cpp new file mode 100644 index 00000000..d6784d26 --- /dev/null +++ b/tools/src/librwxxtpp/RtclRw11CntlDEUNA.cpp @@ -0,0 +1,127 @@ +// $Id: RtclRw11CntlDEUNA.cpp 878 2017-04-16 12:28:15Z mueller $ +// +// Copyright 2014-2017 by Walter F.J. Mueller +// +// 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 +// 2017-04-16 878 1.0 Initial version +// 2014-06-09 561 0.1 First draft +// --------------------------------------------------------------------------- + +/*! + \file + \version $Id: RtclRw11CntlDEUNA.cpp 878 2017-04-16 12:28:15Z mueller $ + \brief Implemenation of RtclRw11CntlDEUNA. +*/ + +#include + +#include "librtcltools/RtclNameSet.hpp" + +#include "RtclRw11CntlDEUNA.hpp" +#include "RtclRw11UnitDEUNA.hpp" + +using namespace std; + +/*! + \class Retro::RtclRw11CntlDEUNA + \brief FIXME_docs +*/ + +// all method definitions in namespace Retro +namespace Retro { + +//------------------------------------------+----------------------------------- +//! Constructor + +RtclRw11CntlDEUNA::RtclRw11CntlDEUNA() + : RtclRw11CntlBase("Rw11CntlDEUNA","ether") +{ + Rw11CntlDEUNA* pobj = &Obj(); + fGets.Add ("dpa", + boost::bind(&Rw11CntlDEUNA::MacDefault, pobj)); + fGets.Add ("rxpoll", + boost::bind(&Rw11CntlDEUNA::RxPollTime, pobj)); + fGets.Add ("rxqlim", + boost::bind(&Rw11CntlDEUNA::RxQueLimit, pobj)); + fGets.Add ("run", + boost::bind(&Rw11CntlDEUNA::Running, pobj)); + + fSets.Add ("type", + boost::bind(&Rw11CntlDEUNA::SetType,pobj, _1)); + fSets.Add ("dpa", + boost::bind(&Rw11CntlDEUNA::SetMacDefault,pobj, _1)); + fSets.Add ("rxpoll", + boost::bind(&Rw11CntlDEUNA::SetRxPollTime,pobj, _1)); + fSets.Add ("rxqlim", + boost::bind(&Rw11CntlDEUNA::SetRxQueLimit,pobj, _1)); +} + +//------------------------------------------+----------------------------------- +//! Destructor + +RtclRw11CntlDEUNA::~RtclRw11CntlDEUNA() +{} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +int RtclRw11CntlDEUNA::FactoryCmdConfig(RtclArgs& args, RtclRw11Cpu& cpu) +{ + static RtclNameSet optset("-base|-lam"); + + string cntlname(cpu.Obj().NextCntlName("xu")); + string cntlcmd = cpu.CommandName() + cntlname; + + uint16_t base = Rw11CntlDEUNA::kIbaddr; + int lam = Rw11CntlDEUNA::kLam; + + string opt; + while (args.NextOpt(opt, optset)) { + if (opt == "-base") { + if (!args.GetArg("base", base, 0177776, 0160000)) return kERR; + } else if (opt == "-lam") { + if (!args.GetArg("lam", lam, 0, 15)) return kERR; + } + } + if (!args.AllDone()) return kERR; + + // configure controller + Obj().Config(cntlname, base, lam); + + // install in CPU + cpu.Obj().AddCntl(dynamic_pointer_cast(ObjSPtr())); + + // finally create tcl command + CreateObjectCmd(args.Interp(), cntlcmd.c_str()); + + // and create unit commands + for (size_t i=0; i +// +// 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 +// 2017-04-16 878 1.0 Initial version +// 2014-06-09 561 0.1 First draft +// --------------------------------------------------------------------------- + + +/*! + \file + \version $Id: RtclRw11CntlDEUNA.hpp 878 2017-04-16 12:28:15Z mueller $ + \brief Declaration of class RtclRw11CntlDEUNA. +*/ + +#ifndef included_Retro_RtclRw11CntlDEUNA +#define included_Retro_RtclRw11CntlDEUNA 1 + +#include "RtclRw11CntlBase.hpp" +#include "librw11/Rw11CntlDEUNA.hpp" + +namespace Retro { + + class RtclRw11CntlDEUNA : public RtclRw11CntlBase { + public: + RtclRw11CntlDEUNA(); + ~RtclRw11CntlDEUNA(); + + virtual int FactoryCmdConfig(RtclArgs& args, RtclRw11Cpu& cpu); + + protected: + virtual int M_default(RtclArgs& args); + }; + +} // end namespace Retro + +//#include "RtclRw11CntlDEUNA.ipp" + +#endif diff --git a/tools/src/librwxxtpp/RtclRw11CntlFactory.cpp b/tools/src/librwxxtpp/RtclRw11CntlFactory.cpp index dbb71bf6..96ff2682 100644 --- a/tools/src/librwxxtpp/RtclRw11CntlFactory.cpp +++ b/tools/src/librwxxtpp/RtclRw11CntlFactory.cpp @@ -1,6 +1,6 @@ -// $Id: RtclRw11CntlFactory.cpp 683 2015-05-17 21:54:35Z mueller $ +// $Id: RtclRw11CntlFactory.cpp 847 2017-01-29 22:38:42Z mueller $ // -// Copyright 2013-2015 by Walter F.J. Mueller +// Copyright 2013-2017 by Walter F.J. Mueller // // 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 @@ -13,6 +13,7 @@ // // Revision History: // Date Rev Version Comment +// 2017-01-29 847 1.1.4 add DEUNA // 2015-03-21 659 1.1.3 add RPRM (later renamed to RHRP) // 2015-01-04 630 1.1.2 RL11 back in // 2014-06-27 565 1.1.1 temporarily hide RL11 @@ -24,7 +25,7 @@ /*! \file - \version $Id: RtclRw11CntlFactory.cpp 683 2015-05-17 21:54:35Z mueller $ + \version $Id: RtclRw11CntlFactory.cpp 847 2017-01-29 22:38:42Z mueller $ \brief Implemenation of global function RtclRw11CntlFactory. */ @@ -37,6 +38,7 @@ #include "RtclRw11CntlRL11.hpp" #include "RtclRw11CntlRHRP.hpp" #include "RtclRw11CntlTM11.hpp" +#include "RtclRw11CntlDEUNA.hpp" #include "RtclRw11CntlLP11.hpp" #include "RtclRw11CntlPC11.hpp" @@ -79,6 +81,11 @@ int RtclRw11CntlFactory(RtclArgs& args, RtclRw11Cpu& cpu) if(pobj->FactoryCmdConfig(args, cpu) != TCL_OK) return TCL_ERROR; pobj.release(); + } else if (type == "deuna") { // deuna ------------------------- + unique_ptr pobj(new RtclRw11CntlDEUNA()); + if(pobj->FactoryCmdConfig(args, cpu) != TCL_OK) return TCL_ERROR; + pobj.release(); + } else if (type == "lp11") { // lp11 -------------------------- unique_ptr pobj(new RtclRw11CntlLP11()); if(pobj->FactoryCmdConfig(args, cpu) != TCL_OK) return TCL_ERROR; diff --git a/tools/src/librwxxtpp/RtclRw11UnitDEUNA.cpp b/tools/src/librwxxtpp/RtclRw11UnitDEUNA.cpp new file mode 100644 index 00000000..27838dad --- /dev/null +++ b/tools/src/librwxxtpp/RtclRw11UnitDEUNA.cpp @@ -0,0 +1,56 @@ +// $Id: RtclRw11UnitDEUNA.cpp 870 2017-04-08 18:24:34Z mueller $ +// +// Copyright 2014-2017 by Walter F.J. Mueller +// +// 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 +// 2017-04-08 870 1.0 Initial version +// 2014-06-09 561 0.1 First draft +// --------------------------------------------------------------------------- + +/*! + \file + \version $Id: RtclRw11UnitDEUNA.cpp 870 2017-04-08 18:24:34Z mueller $ + \brief Implemenation of RtclRw11UnitDEUNA. +*/ + +#include "RtclRw11UnitDEUNA.hpp" + +using namespace std; + +/*! + \class Retro::RtclRw11UnitDEUNA + \brief FIXME_docs +*/ + +// all method definitions in namespace Retro +namespace Retro { + +//------------------------------------------+----------------------------------- +//! Constructor + +RtclRw11UnitDEUNA::RtclRw11UnitDEUNA(Tcl_Interp* interp, + const std::string& unitcmd, + const boost::shared_ptr& spunit) + : RtclRw11UnitBase("Rw11UnitDEUNA", spunit) +{ + CreateObjectCmd(interp, unitcmd.c_str()); +} + +//------------------------------------------+----------------------------------- +//! Destructor + +RtclRw11UnitDEUNA::~RtclRw11UnitDEUNA() +{} + +} // end namespace Retro diff --git a/tools/src/librwxxtpp/RtclRw11UnitDEUNA.hpp b/tools/src/librwxxtpp/RtclRw11UnitDEUNA.hpp new file mode 100644 index 00000000..0e090a08 --- /dev/null +++ b/tools/src/librwxxtpp/RtclRw11UnitDEUNA.hpp @@ -0,0 +1,52 @@ +// $Id: RtclRw11UnitDEUNA.hpp 870 2017-04-08 18:24:34Z mueller $ +// +// Copyright 2014-2017 by Walter F.J. Mueller +// +// 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 +// 2017-04-08 870 1.0 Initial version +// 2014-06-09 561 0.1 First draft +// --------------------------------------------------------------------------- + + +/*! + \file + \version $Id: RtclRw11UnitDEUNA.hpp 870 2017-04-08 18:24:34Z mueller $ + \brief Declaration of class RtclRw11UnitDEUNA. +*/ + +#ifndef included_Retro_RtclRw11UnitDEUNA +#define included_Retro_RtclRw11UnitDEUNA 1 + +#include "librw11/Rw11UnitDEUNA.hpp" +#include "librw11/Rw11CntlDEUNA.hpp" + +#include "RtclRw11UnitBase.hpp" + +namespace Retro { + +class RtclRw11UnitDEUNA : public RtclRw11UnitBase { + public: + RtclRw11UnitDEUNA(Tcl_Interp* interp, + const std::string& unitcmd, + const boost::shared_ptr& spunit); + ~RtclRw11UnitDEUNA(); + + protected: + }; + +} // end namespace Retro + +//#include "RtclRw11UnitDEUNA.ipp" + +#endif diff --git a/tools/tcl/rw11/util.tcl b/tools/tcl/rw11/util.tcl index df5ee925..a5f82f0d 100644 --- a/tools/tcl/rw11/util.tcl +++ b/tools/tcl/rw11/util.tcl @@ -1,6 +1,6 @@ -# $Id: util.tcl 722 2015-12-30 19:45:46Z mueller $ +# $Id: util.tcl 849 2017-02-05 22:30:03Z mueller $ # -# Copyright 2013-2015 by Walter F.J. Mueller +# Copyright 2013-2017 by Walter F.J. Mueller # # 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 @@ -13,6 +13,7 @@ # # Revision History: # Date Rev Version Comment +# 2017-02-04 848 1.3.7 add DEUNA; setup_cntl: handle not found devices # 2015-12-30 721 1.3.6 BUGFIX: setup_ostr: adopt to use args2opts # 2015-07-25 704 1.3.5 use args2opts # 2015-05-17 683 1.3.4 setup_sys: add TM11 @@ -73,6 +74,7 @@ namespace eval rw11 { cpu0 add rl11 cpu0 add rhrp cpu0 add tm11 + cpu0 add deuna cpu0 add lp11 cpu0 add pc11 rlw start @@ -199,10 +201,13 @@ namespace eval rw11 { if {[info commands $ccmd] eq ""} { # create controller, if needed $cpu add $ctype } +# if {![$ccmd get found]} { # quit if not found +# return 0 +# } if {![$ccmd get started]} { # start it, if needed $ccmd start } - return "" + return 1 } #