#ifndef CPSW_PROTO_MOD_SRP_H #define CPSW_PROTO_MOD_SRP_H #include #include #include class CProtoModSRPMux; typedef shared_ptr ProtoModSRPMux; class CSRPPort; typedef shared_ptr SRPPort; class CProtoModSRPMux : public CShObj, public CProtoModImpl { public: const static int VC_MIN = 0; // the code relies on VC occupying 1 byte const static int VC_MAX = 255; private: weak_ptr downstream_[VC_MAX-VC_MIN+1]; INoSsiDev::ProtocolVersion protoVersion_; protected: ProtoPort upstream_; CProtoModSRPMux(const CProtoModSRPMux &orig, Key &k) : CShObj(k), protoVersion_(orig.protoVersion_) { throw InternalError("Clone not implemented"); } public: CProtoModSRPMux(Key &k, INoSsiDev::ProtocolVersion protoVersion) : CShObj(k), protoVersion_(protoVersion) { } // range of bits in TID that the downstream user may occupy virtual int getTidLsb() { return 0; } virtual int getTidNumBits() { return 24; } virtual INoSsiDev::ProtocolVersion getProtoVersion() { return protoVersion_; } // in case there is no downstream module virtual SRPPort createPort(int vc); virtual bool pushDown(BufChain bc, const CTimeout *rel_timeout); virtual SRPPort findPort(int vc) { if ( vc < VC_MIN || vc > VC_MAX ) throw InvalidArgError("Virtual channel number out of range"); if ( downstream_[ vc - VC_MIN ].expired() ) return SRPPort(); return SRPPort( downstream_[ vc - VC_MIN ] ); } virtual CProtoModSRPMux *clone(Key k) { return new CProtoModSRPMux( *this, k ); } virtual ~CProtoModSRPMux() { } }; class CSRPPort : public CShObj, public CPortImpl { private: int vc_; // we use strong pointers in the upstream direction // and the 'owner' represents this. // Thus the 'downstream' vector in the protocol // module must host weak pointers ProtoModSRPMux owner_; weak_ptr< ProtoMod::element_type > downstream_; protected: CSRPPort(const CSRPPort &orig, Key k) : CShObj(k), CPortImpl(orig) { } virtual ProtoPort getSelfAsProtoPort() { return getSelfAs(); } virtual BufChain processOutput(BufChain bc); public: CSRPPort(Key &k, ProtoModSRPMux owner, int vc) : CShObj(k), CPortImpl(1), // queue depth 1 is enough for synchronous operations vc_(vc), owner_(owner) { } int getVC() { return vc_; } protected: friend class CProtoModSRPMux; public: virtual ProtoMod getProtoMod() { return owner_; } virtual ProtoModSRPMux getProtoModAsSRPMux() { return owner_; } virtual INoSsiDev::ProtocolVersion getProtoVersion() { return ProtoModSRPMux( owner_ )->getProtoVersion(); } virtual void attach(ProtoMod m) { if ( ! downstream_.expired() ) { throw ConfigurationError("Already a module attached downstream"); } downstream_ = m; m->attach( getSelfAs() ); } virtual ProtoPort getUpstreamPort() { ProtoMod owner = getProtoMod(); ProtoPort rval; if ( owner ) rval = owner->getUpstreamPort(); return rval; } virtual ~CSRPPort() { } virtual int iMatch(ProtoPortMatchParams *cmp); }; #endif