📄 c-bkend4.html
字号:
<dd><pre class="Code2"><b><a name="85820">#include "rw/queuecol.h" #ifdef WIN32 #ifdef ERROR #undef ERROR #endif #endif</a></b></pre></dl><dd><p class="Body"><a name="85827"> </a>Next, include the header file for the ACE C API, <b class="file">ace/api.h</b>. Include it at this point rather than later, with the other BEDK header files, because it includes Windows header files, and they must be included before the system headers. The undefining and redefining of ERROR is required when Windows header files are included because Windows uses a non-standard ERROR definition.</p><dl class="margin"><dd><pre class="Code2"><b><a name="85828">#include "ace/api.h" // ACE's API header file #ifdef WIN32 #ifdef ERROR #undef ERROR #endif #define ERROR (-1) #endif</a></b></pre></dl><dd><p class="Body"><a name="85836"> </a>Next, include Tornado header files; <b class="file">wdb.h</b> defines the WDB data structures used to pass information between the back end and the target server. </p><dl class="margin"><dd><pre class="Code2"><b><a name="85837">#include "host.h" #include "tgtlib.h" #include "wpwrutil.h" #include "wdb.h"</a></b></pre></dl><dd><p class="Body"><a name="85841"> </a>Finally, include <b class="file">backend.h</b>, which pulls in the declaration of <b class="symbol_lc">Backend_T </b>(the back-end abstract base class) and other back-end-specific header files.</p></dl><dl class="margin"><dd><pre class="Code"><b><a name="85842">#include "backend.h" #include "event.h" #include "bdmExcLib.h"</a></b></pre></dl><dl class="margin"><dd><p class="Body"><a name="85845"> </a>Next, create a new link ID to identify your back end as a unique target-link type. This should be done by defining a macro <b class="symbol_UC">TGT_LINK_BDM_ACE</b> in <b class="library">tgtlib.h</b>. You should choose an unused number in the 0x200 range.</p></dl><dl class="margin"><dd><pre class="Code"><b><a name="85846">#ifndef TGT_LINK_BDM_ACE // Should be defined in tgtlib.h #define TGT_LINK_BDM_ACE (0x201) /* ACE BDM support */ #endif</a></b></pre></dl><dl class="margin"><dd><p class="Body"><a name="85849"> </a>Now, declare the <b class="symbol_lc">Ace_T</b> back-end class as shown below. To reuse the back-end framework and services implemented in <b class="symbol_lc">Backend_T</b>, you must derive your vendor-specific back end from it. It is declared in <i class="textVariable">installDir</i><b class="file">/host/src/tgtsvr/backend/bedk/backend.h</b>. The <b class="symbol_lc">Ace_T</b> constructor has the same arguments as the <b class="routine"><i class="routine">acecpu32Init</i></b><b>( )</b> routine. It is automatically called when the actual <b class="symbol_lc">Ace_T</b> back-end object is allocated. The destructor must be declared <i class="term">virtual</i> because <b class="symbol_lc">Ace_T</b> has virtual functions.</p></dl><dl class="margin"><dd><pre class="Code"><b><a name="85850">class Ace_T : public Backend_T { public: </a></b><dd> <b><a name="85854"> // Constructors and Destructors. Ace_T (char * tgtName, u_int timeout, u_int retryNum, char * devName, u_int param, TGT_OPS * pTgtOps, BKEND_INFO * pBkendInfo); virtual ~Ace_T (); </a></b></pre></dl><dl class="margin"><dd><p class="Body"><a name="85860"> </a>Once the constructor and destructor have been declared, declare the mandatory back-end methods. These methods are listed in <b class="file">backend.h</b>.</p></dl><dl class="margin"><dd><pre class="Code"><b><a name="85861"> ///////////////////////////////////////////////////////////////// // Declare back end member functions which need to be over-ridden in // the vendor-specific back end. // Declaration of mandatory member functions. UINT32 tgtPing_m (void); UINT32 tgtConnect_m (WDB_TGT_INFO * pTgtInfo); UINT32 tgtDisconnect_m (void); ...</a></b></pre></dl><dl class="margin"><dd><p class="Body"><a name="85872"> </a>For the present, ignore the optional member functions. If your emulator supports a faster way of performing these operations than the generic implementation provided by the <b class="symbol_lc">Backend_T</b> class, you may decide to implement them later. Typically, <b class="symbol_lc">Backend_T</b> implements these methods by reading or writing a block of target memory. If your emulator supports an operation (for example, memory fill) directly, you will gain performance by using your emulator's primitive.</p></dl><dl class="margin"><dd><pre class="Code"><b><a name="85873"> // optional member functions ...</a></b></pre></dl><dl class="margin"><dd><p class="Body"><a name="85875"> </a>Now declare the mandatory helper methods. <b class="routine"><i class="routine">Ace_T::fdGet_m</i></b><b>( )</b> should return the event file descriptor, whose activity indicates that an event has occurred on the target. <b class="routine"><i class="routine">Ace_T::halt_m</i></b><b>( )</b> and <b class="routine"><i class="routine">Ace_T::unhalt_m</i></b><b>( )</b> are used by <b class="symbol_lc">Backend_T</b> whenever it needs to suspend the target's system context or return the target to the state it was in before suspension. Typically, these primitives are used before performing a memory operation like Gopher or checksum.</p></dl><dl class="margin"><dd><pre class="Code"><b><a name="87978">// mandatory helper methods virtual int fdGet_m (); // State management virtual UINT32 halt_m (); virtual UINT32 unhalt_m ();</a></b></pre></dl><dl class="margin"><dd><p class="Body"><a name="87979"> </a>Eventually, you will provide whatever vendor-specific helper methods and data are needed to implement your back-end class, such as <b class="routine"><i class="routine">Ace_T::eventCallBack</i></b><b>( )</b>, which is used to handle target events.</p></dl><dl class="margin"><dd><pre class="Code"><b><a name="85884"> ... // handles asynchronous events in the ACE API static void eventCallBack (ACE_ConnectionHandle, ACE_Event *, void *); ... }; // End of class Ace_T ///////////////////////////////////////////////////////////////////////// #endif /* #ifndef __INCacecpu32Backendh */</a></b></pre></dl><dd><font face="Helvetica, sans-serif" size="-1" class="sans"><h5 class="HU"><i><a name="85896">Implementing the Vendor-Specific Back-End Class Skeleton</a></i></h5></font><dl class="margin"><dd><p class="Body"><a name="85898"> </a>The back-end methods are implemented in <b class="file">acecpu32Backend.cpp</b>. Initially, provide stubs for these methods that log a message to the console when they return successfully. This allows you to validate that the Tornado framework can successfully invoke methods in the new back end before you have coded all the methods. For a discussion of how to implement the mandatory and optional methods, see <a href="c-bkend4.html#86194"><i class="title">2.4.4 Implementing Mandatory Member Functions</i></a> and <a href="c-bkend4.html#86811"><i class="title">2.4.5 Implementing Optional Member Functions</i></a>.</p></dl><dl class="margin"><dd><pre class="Code"><b><a name="85905">/* acecpu32Backend.cpp - implements back end for ACE's SuperBDM */ /* includes */ ...</a></b></pre></dl><dl class="margin"><dd><p class="Body"><a name="85909"> </a>The constructor call has the same prototype as the <b class="routine"><i class="routine">acecpu32Init</i></b><b>( )</b> routine and the <b class="symbol_lc">Backend_T</b> constructor.</p></dl><dl class="margin"><dd><pre class="Code"><b><a name="85910">Ace_T::Ace_T ( char * tgtName, TGT_OPS * pTgtOps, BKEND_INFO * pBkendInfo ) </a></b></pre></dl><dl class="margin"><dd><p class="Body"><a name="85921"> </a>Because <b class="symbol_lc">Ace_T</b> is derived from <b class="symbol_lc">Backend_T</b>, whenever an <b class="symbol_lc">Ace_T</b> object is allocated, <b class="symbol_lc">Backend_T</b>'s constructor is called first. It is a good idea to include the call to <b class="symbol_lc">Backend_T</b>'s constructor in an initializer list as a reminder of this fact, to improve performance, and to make sure the correct <b class="symbol_lc">Backend_T</b> constructor is called. Also, include any aggregate objects used in <b class="symbol_lc">Ace_T</b>, such as event queues and flags.</p></dl><dl class="margin"><dd><pre class="Code"><b><a name="85922"> : Backend_T (tgtName, pTgtOps, pBkendInfo) {</a></b></pre></dl><dl class="margin"><dd><p class="Body"><a name="87987"> </a><b class="symbol_lc">Backend_T</b>'s constructor initializes the generic information in the <b class="symbol_UC">TGT_OPS</b> structure. It also initializes <b class="symbol_UC">BKEND_INFO</b>. In other words, it defines what functions the target server should invoke to perform the various back-end operations. (See <a href="c-bkend2.html#84717"><i class="title">The BKEND_INFO Structure</i></a> and <a href="c-bkend2.html#84771"><i class="title">2.2.2 Back-End Functions</i></a>.) See <i class="textVariable">installDir</i><b class="file">/host/src/tgtsvr/backend/bedk/backend.cpp</b> for functions <b class="symbol_lc">Backend_T</b> initializes. </p><dd><p class="Body"><a name="87995"> </a><b class="symbol_lc">Ace_T</b> must initialize the other information in the <b class="symbol_UC">TGT_OPS</b> structure. Note that when event handling is implemented, the constructor calls <b class="routine"><i class="routine">Ace_T::fdGet_m</i></b><b>( )</b> to determine which event file descriptor the target server should monitor for events on the target. Initially, since event handling has not yet been implemented, you should store <b class="symbol_UC">NONE</b> in <b class="symbol_lc">tgtEventFd</b>. A new Tornado back-end type was specified by defining <b class="symbol_UC">TGT_LINK_BDM_ACE</b> in <b class="library">tgtlib.h</b>.</p></dl><dl class="margin"><dd><pre class="Code"><b><a name="85937"> ... pTgtOps->tgtConnected = FALSE; pTgtOps->tgtEventFd = NONE; // Record event fd. pTgtOps->tgtLink.name = "ACE SuperBDM BDM Mode 1.0.1"; pTgtOps->tgtLink.type = TGT_LINK_BDM_ACE; pTgtOps->tgtLink.speed = param;</a></b></pre></dl><dl class="margin"><dd><p class="Body"><a name="85944"> </a>Log a diagnostic message on completion of the constructor:</p></dl><dl class="margin"><dd><pre class="Code"><b><a name="85945"> // Log diagnostic message WPWR_LOG_MSG ("Ace_T::Ace_T( ) : succeeded!\n"); }</a></b></pre></dl><dl class="margin"><dd><p class="Body"><a name="85949"> </a>Similarly, implement a stub for the destructor. (C++ automatically calls <b class="symbol_lc">Backend_T</b>'s destructor.)</p></dl><dl class="margin"><dd><pre class="Code"><b><a name="85950">Ace_T::~Ace_T () { // Log diagnostic message WPWR_LOG_MSG ("Ace_T::~Ace_T( ) : succeeded!\n"); }</a></b></pre></dl><dl class="margin"><dd><p class="Body"><a name="85957"> </a>Finally, you need to provide stubs for the mandatory back-end methods. To validate the back-end framework, it is helpful if these methods log a message and return the appropriate value to indicate success. Back-end methods have three possible return values. You may find it helpful to implement the three functions shown below so that you can see the return value and which method was invoked.</p></dl><dl class="margin"><dd><pre class="Code"><b><a name="85958">LOCAL UINT32 stubUINT32 (const char * pMethod) { WPWR_LOG_MSG ("Ace_T: - method %s.\n", pMethod); return (WDB_OK); } LOCAL BOOL stubBOOL (const char * pMethod) { WPWR_LOG_MSG ("Ace_T: - method %s.\n", pMethod); return (TRUE); } LOCAL void stubVOID (const char * pMethod) { WPWR_LOG_MSG ("Ace_T: - method %s.\n", pMethod); }</a></b></pre></dl></dl><dl class="margin"><dd><p class="table" callout><table border="0" cellpadding="0" cellspacing="0"><tr valign="top"><td valign="top" width="40"><br><img border="0" alt="*" src="icons/note.gif"></td>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -