1*c120c564SAndrew Turner /*
2*c120c564SAndrew Turner  * \file       trc_pkt_proc_stm.cpp
3*c120c564SAndrew Turner  * \brief      OpenCSD :
4*c120c564SAndrew Turner  *
5*c120c564SAndrew Turner  * \copyright  Copyright (c) 2015, ARM Limited. All Rights Reserved.
6*c120c564SAndrew Turner  */
7*c120c564SAndrew Turner 
8*c120c564SAndrew Turner /*
9*c120c564SAndrew Turner  * Redistribution and use in source and binary forms, with or without modification,
10*c120c564SAndrew Turner  * are permitted provided that the following conditions are met:
11*c120c564SAndrew Turner  *
12*c120c564SAndrew Turner  * 1. Redistributions of source code must retain the above copyright notice,
13*c120c564SAndrew Turner  * this list of conditions and the following disclaimer.
14*c120c564SAndrew Turner  *
15*c120c564SAndrew Turner  * 2. Redistributions in binary form must reproduce the above copyright notice,
16*c120c564SAndrew Turner  * this list of conditions and the following disclaimer in the documentation
17*c120c564SAndrew Turner  * and/or other materials provided with the distribution.
18*c120c564SAndrew Turner  *
19*c120c564SAndrew Turner  * 3. Neither the name of the copyright holder nor the names of its contributors
20*c120c564SAndrew Turner  * may be used to endorse or promote products derived from this software without
21*c120c564SAndrew Turner  * specific prior written permission.
22*c120c564SAndrew Turner  *
23*c120c564SAndrew Turner  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24*c120c564SAndrew Turner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25*c120c564SAndrew Turner  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26*c120c564SAndrew Turner  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27*c120c564SAndrew Turner  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28*c120c564SAndrew Turner  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29*c120c564SAndrew Turner  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30*c120c564SAndrew Turner  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31*c120c564SAndrew Turner  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32*c120c564SAndrew Turner  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33*c120c564SAndrew Turner  */
34*c120c564SAndrew Turner 
35*c120c564SAndrew Turner #include "opencsd/stm/trc_pkt_proc_stm.h"
36*c120c564SAndrew Turner 
37*c120c564SAndrew Turner 
38*c120c564SAndrew Turner // processor object construction
39*c120c564SAndrew Turner // ************************
40*c120c564SAndrew Turner 
41*c120c564SAndrew Turner #ifdef __GNUC__
42*c120c564SAndrew Turner // G++ doesn't like the ## pasting
43*c120c564SAndrew Turner #define STM_PKTS_NAME "PKTP_STM"
44*c120c564SAndrew Turner #else
45*c120c564SAndrew Turner #define STM_PKTS_NAME OCSD_CMPNAME_PREFIX_PKTPROC##"_STM"
46*c120c564SAndrew Turner #endif
47*c120c564SAndrew Turner 
48*c120c564SAndrew Turner static const uint32_t STM_SUPPORTED_OP_FLAGS = OCSD_OPFLG_PKTPROC_COMMON;
49*c120c564SAndrew Turner 
TrcPktProcStm()50*c120c564SAndrew Turner TrcPktProcStm::TrcPktProcStm() : TrcPktProcBase(STM_PKTS_NAME)
51*c120c564SAndrew Turner {
52*c120c564SAndrew Turner     initObj();
53*c120c564SAndrew Turner }
54*c120c564SAndrew Turner 
TrcPktProcStm(int instIDNum)55*c120c564SAndrew Turner TrcPktProcStm::TrcPktProcStm(int instIDNum) : TrcPktProcBase(STM_PKTS_NAME, instIDNum)
56*c120c564SAndrew Turner {
57*c120c564SAndrew Turner     initObj();
58*c120c564SAndrew Turner }
59*c120c564SAndrew Turner 
~TrcPktProcStm()60*c120c564SAndrew Turner TrcPktProcStm::~TrcPktProcStm()
61*c120c564SAndrew Turner {
62*c120c564SAndrew Turner     getRawPacketMonAttachPt()->set_notifier(0);
63*c120c564SAndrew Turner }
64*c120c564SAndrew Turner 
initObj()65*c120c564SAndrew Turner void TrcPktProcStm::initObj()
66*c120c564SAndrew Turner {
67*c120c564SAndrew Turner     m_supported_op_flags = STM_SUPPORTED_OP_FLAGS;
68*c120c564SAndrew Turner     initProcessorState();
69*c120c564SAndrew Turner     getRawPacketMonAttachPt()->set_notifier(&mon_in_use);
70*c120c564SAndrew Turner     buildOpTables();
71*c120c564SAndrew Turner }
72*c120c564SAndrew Turner 
73*c120c564SAndrew Turner // implementation packet processing interface overrides
74*c120c564SAndrew Turner // ************************
processData(const ocsd_trc_index_t index,const uint32_t dataBlockSize,const uint8_t * pDataBlock,uint32_t * numBytesProcessed)75*c120c564SAndrew Turner ocsd_datapath_resp_t TrcPktProcStm::processData(  const ocsd_trc_index_t index,
76*c120c564SAndrew Turner                                             const uint32_t dataBlockSize,
77*c120c564SAndrew Turner                                             const uint8_t *pDataBlock,
78*c120c564SAndrew Turner                                             uint32_t *numBytesProcessed)
79*c120c564SAndrew Turner {
80*c120c564SAndrew Turner     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
81*c120c564SAndrew Turner     m_p_data_in = pDataBlock;
82*c120c564SAndrew Turner     m_data_in_size = dataBlockSize;
83*c120c564SAndrew Turner     m_data_in_used = 0;
84*c120c564SAndrew Turner 
85*c120c564SAndrew Turner     // while there is data and a continue response on the data path
86*c120c564SAndrew Turner     while(  dataToProcess() && OCSD_DATA_RESP_IS_CONT(resp) )
87*c120c564SAndrew Turner     {
88*c120c564SAndrew Turner         try
89*c120c564SAndrew Turner         {
90*c120c564SAndrew Turner             switch(m_proc_state)
91*c120c564SAndrew Turner             {
92*c120c564SAndrew Turner             case WAIT_SYNC:
93*c120c564SAndrew Turner                 waitForSync(index);
94*c120c564SAndrew Turner                 break;
95*c120c564SAndrew Turner 
96*c120c564SAndrew Turner             case PROC_HDR:
97*c120c564SAndrew Turner                 m_packet_index = index + m_data_in_used;
98*c120c564SAndrew Turner                 if(readNibble())
99*c120c564SAndrew Turner                 {
100*c120c564SAndrew Turner                     m_proc_state = PROC_DATA;   // read the header nibble, next if any has to be data
101*c120c564SAndrew Turner                     m_pCurrPktFn = m_1N_ops[m_nibble]; // set packet function and fall through
102*c120c564SAndrew Turner                 }
103*c120c564SAndrew Turner                 else
104*c120c564SAndrew Turner                     break;
105*c120c564SAndrew Turner 
106*c120c564SAndrew Turner             case PROC_DATA:
107*c120c564SAndrew Turner                 (this->*m_pCurrPktFn)();
108*c120c564SAndrew Turner 
109*c120c564SAndrew Turner                 // if we have enough to send, fall through, otherwise stop
110*c120c564SAndrew Turner                 if(m_proc_state != SEND_PKT)
111*c120c564SAndrew Turner                     break;
112*c120c564SAndrew Turner 
113*c120c564SAndrew Turner             case SEND_PKT:
114*c120c564SAndrew Turner                 resp = outputPacket();
115*c120c564SAndrew Turner                 break;
116*c120c564SAndrew Turner             }
117*c120c564SAndrew Turner         }
118*c120c564SAndrew Turner         catch(ocsdError &err)
119*c120c564SAndrew Turner         {
120*c120c564SAndrew Turner             LogError(err);
121*c120c564SAndrew Turner             if( ((err.getErrorCode() == OCSD_ERR_BAD_PACKET_SEQ) ||
122*c120c564SAndrew Turner                  (err.getErrorCode() == OCSD_ERR_INVALID_PCKT_HDR)) &&
123*c120c564SAndrew Turner                  !(getComponentOpMode() & OCSD_OPFLG_PKTPROC_ERR_BAD_PKTS))
124*c120c564SAndrew Turner             {
125*c120c564SAndrew Turner                 // send invalid packets up the pipe to let the next stage decide what to do.
126*c120c564SAndrew Turner                 resp = outputPacket();
127*c120c564SAndrew Turner                 if(getComponentOpMode() & OCSD_OPFLG_PKTPROC_UNSYNC_ON_BAD_PKTS)
128*c120c564SAndrew Turner                     m_proc_state = WAIT_SYNC;
129*c120c564SAndrew Turner             }
130*c120c564SAndrew Turner             else
131*c120c564SAndrew Turner             {
132*c120c564SAndrew Turner                 // bail out on any other error.
133*c120c564SAndrew Turner                 resp = OCSD_RESP_FATAL_INVALID_DATA;
134*c120c564SAndrew Turner             }
135*c120c564SAndrew Turner         }
136*c120c564SAndrew Turner         catch(...)
137*c120c564SAndrew Turner         {
138*c120c564SAndrew Turner             /// vv bad at this point.
139*c120c564SAndrew Turner             resp = OCSD_RESP_FATAL_SYS_ERR;
140*c120c564SAndrew Turner             ocsdError fatal = ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_FAIL,m_packet_index,m_config->getTraceID());
141*c120c564SAndrew Turner             fatal.setMessage("Unknown System Error decoding trace.");
142*c120c564SAndrew Turner             LogError(fatal);
143*c120c564SAndrew Turner         }
144*c120c564SAndrew Turner     }
145*c120c564SAndrew Turner 
146*c120c564SAndrew Turner     *numBytesProcessed = m_data_in_used;
147*c120c564SAndrew Turner     return resp;
148*c120c564SAndrew Turner 
149*c120c564SAndrew Turner }
150*c120c564SAndrew Turner 
onEOT()151*c120c564SAndrew Turner ocsd_datapath_resp_t TrcPktProcStm::onEOT()
152*c120c564SAndrew Turner {
153*c120c564SAndrew Turner     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
154*c120c564SAndrew Turner     if(m_num_nibbles > 0)   // there is a partial packet in flight
155*c120c564SAndrew Turner     {
156*c120c564SAndrew Turner         m_curr_packet.updateErrType(STM_PKT_INCOMPLETE_EOT);    // re mark as incomplete
157*c120c564SAndrew Turner         resp = outputPacket();
158*c120c564SAndrew Turner     }
159*c120c564SAndrew Turner     return resp;
160*c120c564SAndrew Turner }
161*c120c564SAndrew Turner 
onReset()162*c120c564SAndrew Turner ocsd_datapath_resp_t TrcPktProcStm::onReset()
163*c120c564SAndrew Turner {
164*c120c564SAndrew Turner     initProcessorState();
165*c120c564SAndrew Turner     return OCSD_RESP_CONT;
166*c120c564SAndrew Turner }
167*c120c564SAndrew Turner 
onFlush()168*c120c564SAndrew Turner ocsd_datapath_resp_t TrcPktProcStm::onFlush()
169*c120c564SAndrew Turner {
170*c120c564SAndrew Turner     // packet processor never holds on to flushable data (may have partial packet,
171*c120c564SAndrew Turner     // but any full packets are immediately sent)
172*c120c564SAndrew Turner     return OCSD_RESP_CONT;
173*c120c564SAndrew Turner }
174*c120c564SAndrew Turner 
onProtocolConfig()175*c120c564SAndrew Turner ocsd_err_t TrcPktProcStm::onProtocolConfig()
176*c120c564SAndrew Turner {
177*c120c564SAndrew Turner     return OCSD_OK;  // nothing to do on config for this processor
178*c120c564SAndrew Turner }
179*c120c564SAndrew Turner 
isBadPacket() const180*c120c564SAndrew Turner const bool TrcPktProcStm::isBadPacket() const
181*c120c564SAndrew Turner {
182*c120c564SAndrew Turner     return m_curr_packet.isBadPacket();
183*c120c564SAndrew Turner }
184*c120c564SAndrew Turner 
outputPacket()185*c120c564SAndrew Turner ocsd_datapath_resp_t TrcPktProcStm::outputPacket()
186*c120c564SAndrew Turner {
187*c120c564SAndrew Turner     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
188*c120c564SAndrew Turner     resp = outputOnAllInterfaces(m_packet_index,&m_curr_packet,&m_curr_packet.type,m_packet_data);
189*c120c564SAndrew Turner     m_packet_data.clear();
190*c120c564SAndrew Turner     initNextPacket();
191*c120c564SAndrew Turner     if(m_nibble_2nd_valid)
192*c120c564SAndrew Turner         savePacketByte(m_nibble_2nd << 4);     // put the unused nibble back on to the data stack and pad for output next time.
193*c120c564SAndrew Turner     m_proc_state = m_bStreamSync ? PROC_HDR : WAIT_SYNC;
194*c120c564SAndrew Turner     return resp;
195*c120c564SAndrew Turner }
196*c120c564SAndrew Turner 
throwBadSequenceError(const char * pszMessage)197*c120c564SAndrew Turner void TrcPktProcStm::throwBadSequenceError(const char *pszMessage /*= ""*/)
198*c120c564SAndrew Turner {
199*c120c564SAndrew Turner     m_curr_packet.updateErrType(STM_PKT_BAD_SEQUENCE);
200*c120c564SAndrew Turner     throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_BAD_PACKET_SEQ,m_packet_index,this->m_config->getTraceID(),pszMessage);
201*c120c564SAndrew Turner }
202*c120c564SAndrew Turner 
throwReservedHdrError(const char * pszMessage)203*c120c564SAndrew Turner void TrcPktProcStm::throwReservedHdrError(const char *pszMessage /*= ""*/)
204*c120c564SAndrew Turner {
205*c120c564SAndrew Turner     m_curr_packet.setPacketType(STM_PKT_RESERVED,false);
206*c120c564SAndrew Turner     throw ocsdError(OCSD_ERR_SEV_ERROR,OCSD_ERR_INVALID_PCKT_HDR,m_packet_index,this->m_config->getTraceID(),pszMessage);
207*c120c564SAndrew Turner }
208*c120c564SAndrew Turner 
209*c120c564SAndrew Turner // processor / packet init
210*c120c564SAndrew Turner // ************************
211*c120c564SAndrew Turner 
initProcessorState()212*c120c564SAndrew Turner void TrcPktProcStm::initProcessorState()
213*c120c564SAndrew Turner {
214*c120c564SAndrew Turner     // clear any state that persists between packets
215*c120c564SAndrew Turner     setProcUnsynced();
216*c120c564SAndrew Turner     clearSyncCount();
217*c120c564SAndrew Turner     m_curr_packet.initStartState();
218*c120c564SAndrew Turner     m_nibble_2nd_valid = false;
219*c120c564SAndrew Turner     initNextPacket();
220*c120c564SAndrew Turner     m_bWaitSyncSaveSuppressed = false;
221*c120c564SAndrew Turner 
222*c120c564SAndrew Turner     m_packet_data.clear();
223*c120c564SAndrew Turner }
224*c120c564SAndrew Turner 
initNextPacket()225*c120c564SAndrew Turner void TrcPktProcStm::initNextPacket()
226*c120c564SAndrew Turner {
227*c120c564SAndrew Turner     // clear state that is unique to each packet
228*c120c564SAndrew Turner     m_bNeedsTS = false;
229*c120c564SAndrew Turner     m_bIsMarker = false;
230*c120c564SAndrew Turner     m_num_nibbles = 0;
231*c120c564SAndrew Turner     m_num_data_nibbles = 0;
232*c120c564SAndrew Turner     m_curr_packet.initNextPacket();
233*c120c564SAndrew Turner }
234*c120c564SAndrew Turner 
235*c120c564SAndrew Turner // search remaining buffer for a start of sync or full sync packet
waitForSync(const ocsd_trc_index_t blk_st_index)236*c120c564SAndrew Turner void TrcPktProcStm::waitForSync(const ocsd_trc_index_t blk_st_index)
237*c120c564SAndrew Turner {
238*c120c564SAndrew Turner     bool bGotData = true;
239*c120c564SAndrew Turner     uint32_t start_offset = m_data_in_used; // record the offset into the buffer at start of this fn.
240*c120c564SAndrew Turner 
241*c120c564SAndrew Turner     // input conditions:
242*c120c564SAndrew Turner     // out of sync - either at start of input stream, or due to bad packet.
243*c120c564SAndrew Turner     // m_data_in_used -> bytes already processed
244*c120c564SAndrew Turner     // m_sync_start -> seen potential start of sync in current stream
245*c120c564SAndrew Turner 
246*c120c564SAndrew Turner     // set a packet index for the start of the data
247*c120c564SAndrew Turner     m_packet_index = blk_st_index + m_data_in_used;
248*c120c564SAndrew Turner     m_num_nibbles = m_is_sync ? m_num_F_nibbles + 1 : m_num_F_nibbles;    // sending unsync data may have cleared down num_nibbles.
249*c120c564SAndrew Turner 
250*c120c564SAndrew Turner     m_bWaitSyncSaveSuppressed = true;   // no need to save bytes until we want to send data.
251*c120c564SAndrew Turner 
252*c120c564SAndrew Turner     while(bGotData && !m_is_sync)
253*c120c564SAndrew Turner     {
254*c120c564SAndrew Turner         bGotData = readNibble();    // read until we have a sync or run out of data
255*c120c564SAndrew Turner     }
256*c120c564SAndrew Turner 
257*c120c564SAndrew Turner     m_bWaitSyncSaveSuppressed = false;
258*c120c564SAndrew Turner 
259*c120c564SAndrew Turner     // no data from first attempt to read
260*c120c564SAndrew Turner     if(m_num_nibbles == 0)
261*c120c564SAndrew Turner         return;
262*c120c564SAndrew Turner 
263*c120c564SAndrew Turner     // we have found a sync or run out of data
264*c120c564SAndrew Turner     // five possible scenarios
265*c120c564SAndrew Turner     // a) all data none sync data.
266*c120c564SAndrew Turner     // b) some none sync data + start of sync sequence
267*c120c564SAndrew Turner     // c) some none sync data + full sync sequence in this frame
268*c120c564SAndrew Turner     // d) full sync sequence @ start of this frame followed by ???
269*c120c564SAndrew Turner     // e) completion of sync sequence in this frame (from b)).
270*c120c564SAndrew Turner 
271*c120c564SAndrew Turner     if(!bGotData || m_num_nibbles > 22)
272*c120c564SAndrew Turner     {
273*c120c564SAndrew Turner         // for a), b), c) send the none sync data then re-enter
274*c120c564SAndrew Turner         // if out of data, or sync with some previous data, this is sent as unsynced.
275*c120c564SAndrew Turner 
276*c120c564SAndrew Turner         m_curr_packet.setPacketType(STM_PKT_NOTSYNC,false);
277*c120c564SAndrew Turner         if(mon_in_use.usingMonitor())
278*c120c564SAndrew Turner         {
279*c120c564SAndrew Turner             uint8_t nibbles_to_send = m_num_nibbles - (m_is_sync ? 22 : m_num_F_nibbles);
280*c120c564SAndrew Turner             uint8_t bytes_to_send = (nibbles_to_send / 2) + (nibbles_to_send % 2);
281*c120c564SAndrew Turner             for(uint8_t i = 0; i < bytes_to_send; i++)
282*c120c564SAndrew Turner                 savePacketByte(m_p_data_in[start_offset+i]);
283*c120c564SAndrew Turner         }
284*c120c564SAndrew Turner 
285*c120c564SAndrew Turner         // if we have found a sync then we will re-enter this function with no pre data,
286*c120c564SAndrew Turner         // but the found flags set.
287*c120c564SAndrew Turner     }
288*c120c564SAndrew Turner     else
289*c120c564SAndrew Turner     {
290*c120c564SAndrew Turner         // send the async packet
291*c120c564SAndrew Turner         m_curr_packet.setPacketType(STM_PKT_ASYNC,false);
292*c120c564SAndrew Turner         m_bStreamSync = true;   // mark the stream as synchronised
293*c120c564SAndrew Turner         clearSyncCount();
294*c120c564SAndrew Turner         m_packet_index = m_sync_index;
295*c120c564SAndrew Turner         if(mon_in_use.usingMonitor())
296*c120c564SAndrew Turner         {
297*c120c564SAndrew Turner             // we may not have the full sync packet still in the local buffer so synthesise it.
298*c120c564SAndrew Turner             for(int i = 0; i < 10; i++)
299*c120c564SAndrew Turner                 savePacketByte(0xFF);
300*c120c564SAndrew Turner             savePacketByte(0x0F);
301*c120c564SAndrew Turner         }
302*c120c564SAndrew Turner     }
303*c120c564SAndrew Turner     sendPacket();  // mark packet for sending
304*c120c564SAndrew Turner }
305*c120c564SAndrew Turner 
306*c120c564SAndrew Turner // packet processing routines
307*c120c564SAndrew Turner // ************************
308*c120c564SAndrew Turner // 1 nibble opcodes
stmPktReserved()309*c120c564SAndrew Turner void TrcPktProcStm::stmPktReserved()
310*c120c564SAndrew Turner {
311*c120c564SAndrew Turner     uint16_t bad_opcode = (uint16_t)m_nibble;
312*c120c564SAndrew Turner     m_curr_packet.setD16Payload(bad_opcode);
313*c120c564SAndrew Turner     throwReservedHdrError("STM: Unsupported or Reserved STPv2 Header");
314*c120c564SAndrew Turner }
315*c120c564SAndrew Turner 
stmPktNull()316*c120c564SAndrew Turner void TrcPktProcStm::stmPktNull()
317*c120c564SAndrew Turner {
318*c120c564SAndrew Turner     m_curr_packet.setPacketType(STM_PKT_NULL,false);
319*c120c564SAndrew Turner     if(m_bNeedsTS)
320*c120c564SAndrew Turner     {
321*c120c564SAndrew Turner         m_pCurrPktFn = &TrcPktProcStm::stmExtractTS;
322*c120c564SAndrew Turner         (this->*m_pCurrPktFn)();
323*c120c564SAndrew Turner     }
324*c120c564SAndrew Turner     else
325*c120c564SAndrew Turner     {
326*c120c564SAndrew Turner         sendPacket();
327*c120c564SAndrew Turner     }
328*c120c564SAndrew Turner }
329*c120c564SAndrew Turner 
stmPktNullTS()330*c120c564SAndrew Turner void TrcPktProcStm::stmPktNullTS()
331*c120c564SAndrew Turner {
332*c120c564SAndrew Turner     pktNeedsTS();
333*c120c564SAndrew Turner     m_pCurrPktFn = &TrcPktProcStm::stmPktNull;
334*c120c564SAndrew Turner     (this->*m_pCurrPktFn)();
335*c120c564SAndrew Turner }
336*c120c564SAndrew Turner 
stmPktM8()337*c120c564SAndrew Turner void TrcPktProcStm::stmPktM8()
338*c120c564SAndrew Turner {
339*c120c564SAndrew Turner     if(m_num_nibbles == 1)    // 1st nibble - header - set type
340*c120c564SAndrew Turner         m_curr_packet.setPacketType(STM_PKT_M8,false);
341*c120c564SAndrew Turner 
342*c120c564SAndrew Turner     stmExtractVal8(3);
343*c120c564SAndrew Turner     if(m_num_nibbles == 3)
344*c120c564SAndrew Turner     {
345*c120c564SAndrew Turner         m_curr_packet.setMaster(m_val8);
346*c120c564SAndrew Turner         sendPacket();
347*c120c564SAndrew Turner     }
348*c120c564SAndrew Turner }
349*c120c564SAndrew Turner 
stmPktMERR()350*c120c564SAndrew Turner void TrcPktProcStm::stmPktMERR()
351*c120c564SAndrew Turner {
352*c120c564SAndrew Turner     if(m_num_nibbles == 1)    // 1st nibble - header - set type
353*c120c564SAndrew Turner         m_curr_packet.setPacketType(STM_PKT_MERR,false);
354*c120c564SAndrew Turner 
355*c120c564SAndrew Turner     stmExtractVal8(3);
356*c120c564SAndrew Turner     if(m_num_nibbles == 3)
357*c120c564SAndrew Turner     {
358*c120c564SAndrew Turner         m_curr_packet.setChannel(0,false);    // MERR resets channel for current master to 0.
359*c120c564SAndrew Turner         m_curr_packet.setD8Payload(m_val8);
360*c120c564SAndrew Turner         sendPacket();
361*c120c564SAndrew Turner     }
362*c120c564SAndrew Turner 
363*c120c564SAndrew Turner }
364*c120c564SAndrew Turner 
stmPktC8()365*c120c564SAndrew Turner void TrcPktProcStm::stmPktC8()
366*c120c564SAndrew Turner {
367*c120c564SAndrew Turner     if(m_num_nibbles == 1)    // 1st nibble - header - set type
368*c120c564SAndrew Turner         m_curr_packet.setPacketType(STM_PKT_C8,false);
369*c120c564SAndrew Turner     stmExtractVal8(3);
370*c120c564SAndrew Turner     if(m_num_nibbles == 3)
371*c120c564SAndrew Turner     {
372*c120c564SAndrew Turner         m_curr_packet.setChannel((uint16_t)m_val8,true);
373*c120c564SAndrew Turner         sendPacket();
374*c120c564SAndrew Turner     }
375*c120c564SAndrew Turner }
376*c120c564SAndrew Turner 
stmPktD4()377*c120c564SAndrew Turner void TrcPktProcStm::stmPktD4()
378*c120c564SAndrew Turner {
379*c120c564SAndrew Turner     if(m_num_nibbles == 1)    // 1st nibble - header - set type
380*c120c564SAndrew Turner     {
381*c120c564SAndrew Turner         m_curr_packet.setPacketType(STM_PKT_D4,m_bIsMarker);
382*c120c564SAndrew Turner         m_num_data_nibbles = 2;  // need 2 nibbles to complete data
383*c120c564SAndrew Turner     }
384*c120c564SAndrew Turner 
385*c120c564SAndrew Turner     if(m_num_nibbles != m_num_data_nibbles)
386*c120c564SAndrew Turner     {
387*c120c564SAndrew Turner         if(readNibble())
388*c120c564SAndrew Turner         {
389*c120c564SAndrew Turner             m_curr_packet.setD4Payload(m_nibble);
390*c120c564SAndrew Turner             if(m_bNeedsTS)
391*c120c564SAndrew Turner             {
392*c120c564SAndrew Turner                 m_pCurrPktFn = &TrcPktProcStm::stmExtractTS;
393*c120c564SAndrew Turner                 (this->*m_pCurrPktFn)();
394*c120c564SAndrew Turner             }
395*c120c564SAndrew Turner             else
396*c120c564SAndrew Turner                 sendPacket();
397*c120c564SAndrew Turner         }
398*c120c564SAndrew Turner     }
399*c120c564SAndrew Turner }
400*c120c564SAndrew Turner 
stmPktD8()401*c120c564SAndrew Turner void TrcPktProcStm::stmPktD8()
402*c120c564SAndrew Turner {
403*c120c564SAndrew Turner     if(m_num_nibbles == 1)    // 1st nibble - header - set type
404*c120c564SAndrew Turner     {
405*c120c564SAndrew Turner         m_curr_packet.setPacketType(STM_PKT_D8,m_bIsMarker);
406*c120c564SAndrew Turner         m_num_data_nibbles = 3; // need 3 nibbles in total to complete data
407*c120c564SAndrew Turner     }
408*c120c564SAndrew Turner 
409*c120c564SAndrew Turner     stmExtractVal8(m_num_data_nibbles);
410*c120c564SAndrew Turner     if(m_num_nibbles == m_num_data_nibbles)
411*c120c564SAndrew Turner     {
412*c120c564SAndrew Turner         m_curr_packet.setD8Payload(m_val8);
413*c120c564SAndrew Turner         if(m_bNeedsTS)
414*c120c564SAndrew Turner         {
415*c120c564SAndrew Turner             m_pCurrPktFn = &TrcPktProcStm::stmExtractTS;
416*c120c564SAndrew Turner             (this->*m_pCurrPktFn)();
417*c120c564SAndrew Turner         }
418*c120c564SAndrew Turner         else
419*c120c564SAndrew Turner         {
420*c120c564SAndrew Turner             sendPacket();
421*c120c564SAndrew Turner         }
422*c120c564SAndrew Turner     }
423*c120c564SAndrew Turner }
424*c120c564SAndrew Turner 
stmPktD16()425*c120c564SAndrew Turner void TrcPktProcStm::stmPktD16()
426*c120c564SAndrew Turner {
427*c120c564SAndrew Turner     if(m_num_nibbles == 1)    // 1st nibble - header - set type
428*c120c564SAndrew Turner     {
429*c120c564SAndrew Turner         m_curr_packet.setPacketType(STM_PKT_D16,m_bIsMarker);
430*c120c564SAndrew Turner         m_num_data_nibbles = 5;
431*c120c564SAndrew Turner     }
432*c120c564SAndrew Turner 
433*c120c564SAndrew Turner     stmExtractVal16(m_num_data_nibbles);
434*c120c564SAndrew Turner     if(m_num_nibbles == m_num_data_nibbles)
435*c120c564SAndrew Turner     {
436*c120c564SAndrew Turner         m_curr_packet.setD16Payload(m_val16);
437*c120c564SAndrew Turner         if(m_bNeedsTS)
438*c120c564SAndrew Turner         {
439*c120c564SAndrew Turner             m_pCurrPktFn = &TrcPktProcStm::stmExtractTS;
440*c120c564SAndrew Turner             (this->*m_pCurrPktFn)();
441*c120c564SAndrew Turner         }
442*c120c564SAndrew Turner         else
443*c120c564SAndrew Turner         {
444*c120c564SAndrew Turner             sendPacket();
445*c120c564SAndrew Turner         }
446*c120c564SAndrew Turner     }
447*c120c564SAndrew Turner }
448*c120c564SAndrew Turner 
stmPktD32()449*c120c564SAndrew Turner void TrcPktProcStm::stmPktD32()
450*c120c564SAndrew Turner {
451*c120c564SAndrew Turner     if(m_num_nibbles == 1)    // 1st nibble - header - set type
452*c120c564SAndrew Turner     {
453*c120c564SAndrew Turner         m_curr_packet.setPacketType(STM_PKT_D32,m_bIsMarker);
454*c120c564SAndrew Turner         m_num_data_nibbles = 9;
455*c120c564SAndrew Turner     }
456*c120c564SAndrew Turner 
457*c120c564SAndrew Turner     stmExtractVal32(m_num_data_nibbles);
458*c120c564SAndrew Turner     if(m_num_nibbles == m_num_data_nibbles)
459*c120c564SAndrew Turner     {
460*c120c564SAndrew Turner         m_curr_packet.setD32Payload(m_val32);
461*c120c564SAndrew Turner         if(m_bNeedsTS)
462*c120c564SAndrew Turner         {
463*c120c564SAndrew Turner             m_pCurrPktFn = &TrcPktProcStm::stmExtractTS;
464*c120c564SAndrew Turner             (this->*m_pCurrPktFn)();
465*c120c564SAndrew Turner         }
466*c120c564SAndrew Turner         else
467*c120c564SAndrew Turner         {
468*c120c564SAndrew Turner             sendPacket();
469*c120c564SAndrew Turner         }
470*c120c564SAndrew Turner     }
471*c120c564SAndrew Turner }
472*c120c564SAndrew Turner 
stmPktD64()473*c120c564SAndrew Turner void TrcPktProcStm::stmPktD64()
474*c120c564SAndrew Turner {
475*c120c564SAndrew Turner     if(m_num_nibbles == 1)    // 1st nibble - header - set type
476*c120c564SAndrew Turner     {
477*c120c564SAndrew Turner         m_curr_packet.setPacketType(STM_PKT_D64,m_bIsMarker);
478*c120c564SAndrew Turner         m_num_data_nibbles = 17;
479*c120c564SAndrew Turner     }
480*c120c564SAndrew Turner 
481*c120c564SAndrew Turner     stmExtractVal64(m_num_data_nibbles);
482*c120c564SAndrew Turner     if(m_num_nibbles == m_num_data_nibbles)
483*c120c564SAndrew Turner     {
484*c120c564SAndrew Turner         m_curr_packet.setD64Payload(m_val64);
485*c120c564SAndrew Turner         if(m_bNeedsTS)
486*c120c564SAndrew Turner         {
487*c120c564SAndrew Turner             m_pCurrPktFn = &TrcPktProcStm::stmExtractTS;
488*c120c564SAndrew Turner             (this->*m_pCurrPktFn)();
489*c120c564SAndrew Turner         }
490*c120c564SAndrew Turner         else
491*c120c564SAndrew Turner         {
492*c120c564SAndrew Turner             sendPacket();
493*c120c564SAndrew Turner         }
494*c120c564SAndrew Turner     }
495*c120c564SAndrew Turner }
496*c120c564SAndrew Turner 
stmPktD4MTS()497*c120c564SAndrew Turner void TrcPktProcStm::stmPktD4MTS()
498*c120c564SAndrew Turner {
499*c120c564SAndrew Turner     pktNeedsTS();
500*c120c564SAndrew Turner     m_bIsMarker = true;
501*c120c564SAndrew Turner     m_pCurrPktFn = &TrcPktProcStm::stmPktD4;
502*c120c564SAndrew Turner     (this->*m_pCurrPktFn)();
503*c120c564SAndrew Turner }
504*c120c564SAndrew Turner 
stmPktD8MTS()505*c120c564SAndrew Turner void TrcPktProcStm::stmPktD8MTS()
506*c120c564SAndrew Turner {
507*c120c564SAndrew Turner     pktNeedsTS();
508*c120c564SAndrew Turner     m_bIsMarker = true;
509*c120c564SAndrew Turner     m_pCurrPktFn = &TrcPktProcStm::stmPktD8;
510*c120c564SAndrew Turner     (this->*m_pCurrPktFn)();
511*c120c564SAndrew Turner }
512*c120c564SAndrew Turner 
stmPktD16MTS()513*c120c564SAndrew Turner void TrcPktProcStm::stmPktD16MTS()
514*c120c564SAndrew Turner {
515*c120c564SAndrew Turner     pktNeedsTS();
516*c120c564SAndrew Turner     m_bIsMarker = true;
517*c120c564SAndrew Turner     m_pCurrPktFn = &TrcPktProcStm::stmPktD16;
518*c120c564SAndrew Turner     (this->*m_pCurrPktFn)();
519*c120c564SAndrew Turner }
520*c120c564SAndrew Turner 
stmPktD32MTS()521*c120c564SAndrew Turner void TrcPktProcStm::stmPktD32MTS()
522*c120c564SAndrew Turner {
523*c120c564SAndrew Turner     pktNeedsTS();
524*c120c564SAndrew Turner     m_bIsMarker = true;
525*c120c564SAndrew Turner     m_pCurrPktFn = &TrcPktProcStm::stmPktD32;
526*c120c564SAndrew Turner     (this->*m_pCurrPktFn)();
527*c120c564SAndrew Turner }
528*c120c564SAndrew Turner 
stmPktD64MTS()529*c120c564SAndrew Turner void TrcPktProcStm::stmPktD64MTS()
530*c120c564SAndrew Turner {
531*c120c564SAndrew Turner     pktNeedsTS();
532*c120c564SAndrew Turner     m_bIsMarker = true;
533*c120c564SAndrew Turner     m_pCurrPktFn = &TrcPktProcStm::stmPktD64;
534*c120c564SAndrew Turner     (this->*m_pCurrPktFn)();
535*c120c564SAndrew Turner }
536*c120c564SAndrew Turner 
stmPktFlagTS()537*c120c564SAndrew Turner void TrcPktProcStm::stmPktFlagTS()
538*c120c564SAndrew Turner {
539*c120c564SAndrew Turner     pktNeedsTS();
540*c120c564SAndrew Turner     m_curr_packet.setPacketType(STM_PKT_FLAG,false);
541*c120c564SAndrew Turner     m_pCurrPktFn = &TrcPktProcStm::stmExtractTS;
542*c120c564SAndrew Turner     (this->*m_pCurrPktFn)();
543*c120c564SAndrew Turner }
544*c120c564SAndrew Turner 
stmPktFExt()545*c120c564SAndrew Turner void TrcPktProcStm::stmPktFExt()
546*c120c564SAndrew Turner {
547*c120c564SAndrew Turner     // no type, look at the next nibble
548*c120c564SAndrew Turner     if(readNibble())
549*c120c564SAndrew Turner     {
550*c120c564SAndrew Turner         // switch in 2N function
551*c120c564SAndrew Turner         m_pCurrPktFn = m_2N_ops[m_nibble];
552*c120c564SAndrew Turner         (this->*m_pCurrPktFn)();
553*c120c564SAndrew Turner     }
554*c120c564SAndrew Turner }
555*c120c564SAndrew Turner 
556*c120c564SAndrew Turner // ************************
557*c120c564SAndrew Turner // 2 nibble opcodes 0xFn
stmPktReservedFn()558*c120c564SAndrew Turner void TrcPktProcStm::stmPktReservedFn()
559*c120c564SAndrew Turner {
560*c120c564SAndrew Turner     uint16_t bad_opcode = 0x00F;
561*c120c564SAndrew Turner     bad_opcode |= ((uint16_t)m_nibble) << 4;
562*c120c564SAndrew Turner     m_curr_packet.setD16Payload(bad_opcode);
563*c120c564SAndrew Turner     throwReservedHdrError("STM: Unsupported or Reserved STPv2 Header");
564*c120c564SAndrew Turner }
565*c120c564SAndrew Turner 
stmPktF0Ext()566*c120c564SAndrew Turner void TrcPktProcStm::stmPktF0Ext()
567*c120c564SAndrew Turner {
568*c120c564SAndrew Turner     // no type yet, look at the next nibble
569*c120c564SAndrew Turner     if(readNibble())
570*c120c564SAndrew Turner     {
571*c120c564SAndrew Turner         // switch in 3N function
572*c120c564SAndrew Turner         m_pCurrPktFn = m_3N_ops[m_nibble];
573*c120c564SAndrew Turner         (this->*m_pCurrPktFn)();
574*c120c564SAndrew Turner     }
575*c120c564SAndrew Turner }
576*c120c564SAndrew Turner 
stmPktGERR()577*c120c564SAndrew Turner void TrcPktProcStm::stmPktGERR()
578*c120c564SAndrew Turner {
579*c120c564SAndrew Turner     if(m_num_nibbles == 2)    // 2nd nibble - header - set type
580*c120c564SAndrew Turner         m_curr_packet.setPacketType(STM_PKT_GERR,false);
581*c120c564SAndrew Turner     stmExtractVal8(4);
582*c120c564SAndrew Turner     if(m_num_nibbles == 4)
583*c120c564SAndrew Turner     {
584*c120c564SAndrew Turner         m_curr_packet.setD8Payload(m_val8);
585*c120c564SAndrew Turner         m_curr_packet.setMaster(0); // GERR sets current master to 0.
586*c120c564SAndrew Turner         sendPacket();
587*c120c564SAndrew Turner     }
588*c120c564SAndrew Turner }
589*c120c564SAndrew Turner 
stmPktC16()590*c120c564SAndrew Turner void TrcPktProcStm::stmPktC16()
591*c120c564SAndrew Turner {
592*c120c564SAndrew Turner     if(m_num_nibbles == 2)    // 2nd nibble - header - set type
593*c120c564SAndrew Turner         m_curr_packet.setPacketType(STM_PKT_C16,false);
594*c120c564SAndrew Turner     stmExtractVal16(6);
595*c120c564SAndrew Turner     if(m_num_nibbles == 6)
596*c120c564SAndrew Turner     {
597*c120c564SAndrew Turner         m_curr_packet.setChannel(m_val16,false);
598*c120c564SAndrew Turner         sendPacket();
599*c120c564SAndrew Turner     }
600*c120c564SAndrew Turner }
601*c120c564SAndrew Turner 
stmPktD4TS()602*c120c564SAndrew Turner void TrcPktProcStm::stmPktD4TS()
603*c120c564SAndrew Turner {
604*c120c564SAndrew Turner     pktNeedsTS();
605*c120c564SAndrew Turner     m_curr_packet.setPacketType(STM_PKT_D4,false); // 2nd nibble, set type here
606*c120c564SAndrew Turner     m_num_data_nibbles = 3; // one more nibble for data
607*c120c564SAndrew Turner     m_pCurrPktFn = &TrcPktProcStm::stmPktD4;
608*c120c564SAndrew Turner     (this->*m_pCurrPktFn)();
609*c120c564SAndrew Turner }
610*c120c564SAndrew Turner 
stmPktD8TS()611*c120c564SAndrew Turner void TrcPktProcStm::stmPktD8TS()
612*c120c564SAndrew Turner {
613*c120c564SAndrew Turner     pktNeedsTS();
614*c120c564SAndrew Turner     m_curr_packet.setPacketType(STM_PKT_D8,false); // 2nd nibble, set type here
615*c120c564SAndrew Turner     m_num_data_nibbles = 4;
616*c120c564SAndrew Turner     m_pCurrPktFn = &TrcPktProcStm::stmPktD8;
617*c120c564SAndrew Turner     (this->*m_pCurrPktFn)();
618*c120c564SAndrew Turner }
619*c120c564SAndrew Turner 
stmPktD16TS()620*c120c564SAndrew Turner void TrcPktProcStm::stmPktD16TS()
621*c120c564SAndrew Turner {
622*c120c564SAndrew Turner     pktNeedsTS();
623*c120c564SAndrew Turner     m_curr_packet.setPacketType(STM_PKT_D16,false); // 2nd nibble, set type here
624*c120c564SAndrew Turner     m_num_data_nibbles = 6;
625*c120c564SAndrew Turner     m_pCurrPktFn = &TrcPktProcStm::stmPktD16;
626*c120c564SAndrew Turner     (this->*m_pCurrPktFn)();
627*c120c564SAndrew Turner }
628*c120c564SAndrew Turner 
stmPktD32TS()629*c120c564SAndrew Turner void TrcPktProcStm::stmPktD32TS()
630*c120c564SAndrew Turner {
631*c120c564SAndrew Turner     pktNeedsTS();
632*c120c564SAndrew Turner     m_curr_packet.setPacketType(STM_PKT_D32,false); // 2nd nibble, set type here
633*c120c564SAndrew Turner     m_num_data_nibbles = 10;
634*c120c564SAndrew Turner     m_pCurrPktFn = &TrcPktProcStm::stmPktD32;
635*c120c564SAndrew Turner     (this->*m_pCurrPktFn)();
636*c120c564SAndrew Turner }
637*c120c564SAndrew Turner 
stmPktD64TS()638*c120c564SAndrew Turner void TrcPktProcStm::stmPktD64TS()
639*c120c564SAndrew Turner {
640*c120c564SAndrew Turner     pktNeedsTS();
641*c120c564SAndrew Turner     m_curr_packet.setPacketType(STM_PKT_D64,false); // 2nd nibble, set type here
642*c120c564SAndrew Turner     m_num_data_nibbles = 18;
643*c120c564SAndrew Turner     m_pCurrPktFn = &TrcPktProcStm::stmPktD64;
644*c120c564SAndrew Turner     (this->*m_pCurrPktFn)();
645*c120c564SAndrew Turner }
646*c120c564SAndrew Turner 
stmPktD4M()647*c120c564SAndrew Turner void TrcPktProcStm::stmPktD4M()
648*c120c564SAndrew Turner {
649*c120c564SAndrew Turner     m_curr_packet.setPacketType(STM_PKT_D4,true); // 2nd nibble, set type here
650*c120c564SAndrew Turner     m_num_data_nibbles = 3; // one more nibble for data
651*c120c564SAndrew Turner     m_pCurrPktFn = &TrcPktProcStm::stmPktD4;
652*c120c564SAndrew Turner     (this->*m_pCurrPktFn)();
653*c120c564SAndrew Turner }
654*c120c564SAndrew Turner 
stmPktD8M()655*c120c564SAndrew Turner void TrcPktProcStm::stmPktD8M()
656*c120c564SAndrew Turner {
657*c120c564SAndrew Turner     m_curr_packet.setPacketType(STM_PKT_D8,true); // 2nd nibble, set type here
658*c120c564SAndrew Turner     m_num_data_nibbles = 4;
659*c120c564SAndrew Turner     m_pCurrPktFn = &TrcPktProcStm::stmPktD8;
660*c120c564SAndrew Turner     (this->*m_pCurrPktFn)();
661*c120c564SAndrew Turner }
662*c120c564SAndrew Turner 
stmPktD16M()663*c120c564SAndrew Turner void TrcPktProcStm::stmPktD16M()
664*c120c564SAndrew Turner {
665*c120c564SAndrew Turner     m_curr_packet.setPacketType(STM_PKT_D16,true);
666*c120c564SAndrew Turner     m_num_data_nibbles = 6;
667*c120c564SAndrew Turner     m_pCurrPktFn = &TrcPktProcStm::stmPktD16;
668*c120c564SAndrew Turner     (this->*m_pCurrPktFn)();
669*c120c564SAndrew Turner }
670*c120c564SAndrew Turner 
stmPktD32M()671*c120c564SAndrew Turner void TrcPktProcStm::stmPktD32M()
672*c120c564SAndrew Turner {
673*c120c564SAndrew Turner     m_curr_packet.setPacketType(STM_PKT_D32,true);
674*c120c564SAndrew Turner     m_num_data_nibbles = 10;
675*c120c564SAndrew Turner     m_pCurrPktFn = &TrcPktProcStm::stmPktD32;
676*c120c564SAndrew Turner     (this->*m_pCurrPktFn)();
677*c120c564SAndrew Turner }
678*c120c564SAndrew Turner 
stmPktD64M()679*c120c564SAndrew Turner void TrcPktProcStm::stmPktD64M()
680*c120c564SAndrew Turner {
681*c120c564SAndrew Turner     m_curr_packet.setPacketType(STM_PKT_D64,true);
682*c120c564SAndrew Turner     m_num_data_nibbles = 18;
683*c120c564SAndrew Turner     m_pCurrPktFn = &TrcPktProcStm::stmPktD64;
684*c120c564SAndrew Turner     (this->*m_pCurrPktFn)();
685*c120c564SAndrew Turner }
686*c120c564SAndrew Turner 
stmPktFlag()687*c120c564SAndrew Turner void TrcPktProcStm::stmPktFlag()
688*c120c564SAndrew Turner {
689*c120c564SAndrew Turner     m_curr_packet.setPacketType(STM_PKT_FLAG,false);
690*c120c564SAndrew Turner     sendPacket();
691*c120c564SAndrew Turner }
692*c120c564SAndrew Turner 
693*c120c564SAndrew Turner // ************************
694*c120c564SAndrew Turner // 3 nibble opcodes 0xF0n
stmPktReservedF0n()695*c120c564SAndrew Turner void TrcPktProcStm::stmPktReservedF0n()
696*c120c564SAndrew Turner {
697*c120c564SAndrew Turner     uint16_t bad_opcode = 0x00F;
698*c120c564SAndrew Turner     bad_opcode |= ((uint16_t)m_nibble) << 8;
699*c120c564SAndrew Turner     m_curr_packet.setD16Payload(bad_opcode);
700*c120c564SAndrew Turner     throwReservedHdrError("STM: Unsupported or Reserved STPv2 Header");
701*c120c564SAndrew Turner }
702*c120c564SAndrew Turner 
stmPktVersion()703*c120c564SAndrew Turner void TrcPktProcStm::stmPktVersion()
704*c120c564SAndrew Turner {
705*c120c564SAndrew Turner     if(m_num_nibbles == 3)
706*c120c564SAndrew Turner         m_curr_packet.setPacketType(STM_PKT_VERSION,false);
707*c120c564SAndrew Turner 
708*c120c564SAndrew Turner     if(readNibble())
709*c120c564SAndrew Turner     {
710*c120c564SAndrew Turner         m_curr_packet.setD8Payload(m_nibble);   // record the version number
711*c120c564SAndrew Turner         switch(m_nibble)
712*c120c564SAndrew Turner         {
713*c120c564SAndrew Turner         case 3:
714*c120c564SAndrew Turner             m_curr_packet.onVersionPkt(STM_TS_NATBINARY); break;
715*c120c564SAndrew Turner         case 4:
716*c120c564SAndrew Turner             m_curr_packet.onVersionPkt(STM_TS_GREY); break;
717*c120c564SAndrew Turner         default:
718*c120c564SAndrew Turner             // not a version we support.
719*c120c564SAndrew Turner             throwBadSequenceError("STM VERSION packet : unrecognised version number.");
720*c120c564SAndrew Turner         }
721*c120c564SAndrew Turner         sendPacket();
722*c120c564SAndrew Turner     }
723*c120c564SAndrew Turner }
724*c120c564SAndrew Turner 
stmPktTrigger()725*c120c564SAndrew Turner void TrcPktProcStm::stmPktTrigger()
726*c120c564SAndrew Turner {
727*c120c564SAndrew Turner     if(m_num_nibbles == 3)
728*c120c564SAndrew Turner         m_curr_packet.setPacketType(STM_PKT_TRIG,false);
729*c120c564SAndrew Turner     stmExtractVal8(5);
730*c120c564SAndrew Turner     if(m_num_nibbles == 5)
731*c120c564SAndrew Turner     {
732*c120c564SAndrew Turner         m_curr_packet.setD8Payload(m_val8);
733*c120c564SAndrew Turner         if(m_bNeedsTS)
734*c120c564SAndrew Turner         {
735*c120c564SAndrew Turner             m_pCurrPktFn = &TrcPktProcStm::stmExtractTS;
736*c120c564SAndrew Turner             (this->*m_pCurrPktFn)();
737*c120c564SAndrew Turner         }
738*c120c564SAndrew Turner         else
739*c120c564SAndrew Turner         {
740*c120c564SAndrew Turner             sendPacket();
741*c120c564SAndrew Turner         }
742*c120c564SAndrew Turner     }
743*c120c564SAndrew Turner }
744*c120c564SAndrew Turner 
stmPktTriggerTS()745*c120c564SAndrew Turner void TrcPktProcStm::stmPktTriggerTS()
746*c120c564SAndrew Turner {
747*c120c564SAndrew Turner     pktNeedsTS();
748*c120c564SAndrew Turner     m_pCurrPktFn = &TrcPktProcStm::stmPktTrigger;
749*c120c564SAndrew Turner     (this->*m_pCurrPktFn)();
750*c120c564SAndrew Turner }
751*c120c564SAndrew Turner 
stmPktFreq()752*c120c564SAndrew Turner void TrcPktProcStm::stmPktFreq()
753*c120c564SAndrew Turner {
754*c120c564SAndrew Turner     if(m_num_nibbles == 3)
755*c120c564SAndrew Turner     {
756*c120c564SAndrew Turner         m_curr_packet.setPacketType(STM_PKT_FREQ,false);
757*c120c564SAndrew Turner         m_val32 = 0;
758*c120c564SAndrew Turner     }
759*c120c564SAndrew Turner     stmExtractVal32(11);
760*c120c564SAndrew Turner     if(m_num_nibbles == 11)
761*c120c564SAndrew Turner     {
762*c120c564SAndrew Turner         m_curr_packet.setD32Payload(m_val32);
763*c120c564SAndrew Turner         sendPacket();
764*c120c564SAndrew Turner     }
765*c120c564SAndrew Turner }
766*c120c564SAndrew Turner 
stmPktASync()767*c120c564SAndrew Turner void TrcPktProcStm::stmPktASync()
768*c120c564SAndrew Turner {
769*c120c564SAndrew Turner     // 2 nibbles - 0xFF - must be an async or error.
770*c120c564SAndrew Turner     bool bCont = true;
771*c120c564SAndrew Turner     while(bCont)
772*c120c564SAndrew Turner     {
773*c120c564SAndrew Turner         bCont = readNibble();
774*c120c564SAndrew Turner         if(bCont)
775*c120c564SAndrew Turner         {
776*c120c564SAndrew Turner             if(m_is_sync)
777*c120c564SAndrew Turner             {
778*c120c564SAndrew Turner                 bCont = false;  // stop reading nibbles
779*c120c564SAndrew Turner                 m_bStreamSync = true;   // mark stream in sync
780*c120c564SAndrew Turner                 m_curr_packet.setPacketType(STM_PKT_ASYNC,false);
781*c120c564SAndrew Turner                 clearSyncCount();
782*c120c564SAndrew Turner                 sendPacket();
783*c120c564SAndrew Turner             }
784*c120c564SAndrew Turner             else if(!m_sync_start)  // no longer valid sync packet
785*c120c564SAndrew Turner             {
786*c120c564SAndrew Turner                 throwBadSequenceError("STM: Invalid ASYNC sequence");
787*c120c564SAndrew Turner             }
788*c120c564SAndrew Turner         }
789*c120c564SAndrew Turner     }
790*c120c564SAndrew Turner }
791*c120c564SAndrew Turner 
792*c120c564SAndrew Turner // ************************
793*c120c564SAndrew Turner // general data processing
794*c120c564SAndrew Turner 
795*c120c564SAndrew Turner // return false if no more data
796*c120c564SAndrew Turner // in an STM byte, 3:0 is 1st nibble in protocol order, 7:4 is 2nd nibble.
readNibble()797*c120c564SAndrew Turner bool TrcPktProcStm::readNibble()
798*c120c564SAndrew Turner {
799*c120c564SAndrew Turner     bool dataFound = true;
800*c120c564SAndrew Turner     if(m_nibble_2nd_valid)
801*c120c564SAndrew Turner     {
802*c120c564SAndrew Turner         m_nibble = m_nibble_2nd;
803*c120c564SAndrew Turner         m_nibble_2nd_valid = false;
804*c120c564SAndrew Turner         m_num_nibbles++;
805*c120c564SAndrew Turner         checkSyncNibble();
806*c120c564SAndrew Turner     }
807*c120c564SAndrew Turner     else if(m_data_in_used < m_data_in_size )
808*c120c564SAndrew Turner     {
809*c120c564SAndrew Turner         m_nibble = m_p_data_in[m_data_in_used++];
810*c120c564SAndrew Turner         savePacketByte(m_nibble);
811*c120c564SAndrew Turner         m_nibble_2nd = (m_nibble >> 4) & 0xF;
812*c120c564SAndrew Turner         m_nibble_2nd_valid = true;
813*c120c564SAndrew Turner         m_nibble &= 0xF;
814*c120c564SAndrew Turner         m_num_nibbles++;
815*c120c564SAndrew Turner         checkSyncNibble();
816*c120c564SAndrew Turner     }
817*c120c564SAndrew Turner     else
818*c120c564SAndrew Turner         dataFound = false;  // no data available
819*c120c564SAndrew Turner     return dataFound;
820*c120c564SAndrew Turner }
821*c120c564SAndrew Turner 
pktNeedsTS()822*c120c564SAndrew Turner void TrcPktProcStm::pktNeedsTS()
823*c120c564SAndrew Turner {
824*c120c564SAndrew Turner     m_bNeedsTS = true;
825*c120c564SAndrew Turner     m_req_ts_nibbles = 0;
826*c120c564SAndrew Turner     m_curr_ts_nibbles = 0;
827*c120c564SAndrew Turner     m_ts_update_value = 0;
828*c120c564SAndrew Turner     m_ts_req_set = false;
829*c120c564SAndrew Turner }
830*c120c564SAndrew Turner 
stmExtractTS()831*c120c564SAndrew Turner void TrcPktProcStm::stmExtractTS()
832*c120c564SAndrew Turner {
833*c120c564SAndrew Turner     if(!m_ts_req_set)
834*c120c564SAndrew Turner     {
835*c120c564SAndrew Turner         if(readNibble())
836*c120c564SAndrew Turner         {
837*c120c564SAndrew Turner             m_req_ts_nibbles = m_nibble;
838*c120c564SAndrew Turner             if(m_nibble == 0xD)
839*c120c564SAndrew Turner                 m_req_ts_nibbles = 14;
840*c120c564SAndrew Turner             else if(m_nibble == 0xE)
841*c120c564SAndrew Turner                 m_req_ts_nibbles = 16;
842*c120c564SAndrew Turner 
843*c120c564SAndrew Turner             if(m_nibble == 0xF)
844*c120c564SAndrew Turner                 throwBadSequenceError("STM: Invalid timestamp size 0xF");
845*c120c564SAndrew Turner             m_ts_req_set = true;
846*c120c564SAndrew Turner         }
847*c120c564SAndrew Turner     }
848*c120c564SAndrew Turner 
849*c120c564SAndrew Turner     if(m_ts_req_set)
850*c120c564SAndrew Turner     {
851*c120c564SAndrew Turner         // if we do not have all the nibbles for the TS, get some...
852*c120c564SAndrew Turner         if(m_req_ts_nibbles != m_curr_ts_nibbles)
853*c120c564SAndrew Turner         {
854*c120c564SAndrew Turner             // extract the correct amount of nibbles for the ts value.
855*c120c564SAndrew Turner             bool bCont = true;
856*c120c564SAndrew Turner             while(bCont && (m_curr_ts_nibbles < m_req_ts_nibbles))
857*c120c564SAndrew Turner             {
858*c120c564SAndrew Turner                 bCont = readNibble();
859*c120c564SAndrew Turner                 if(bCont)
860*c120c564SAndrew Turner                 {
861*c120c564SAndrew Turner                     m_ts_update_value <<= 4;
862*c120c564SAndrew Turner                     m_ts_update_value |= m_nibble;
863*c120c564SAndrew Turner                     m_curr_ts_nibbles++;
864*c120c564SAndrew Turner                 }
865*c120c564SAndrew Turner             }
866*c120c564SAndrew Turner         }
867*c120c564SAndrew Turner 
868*c120c564SAndrew Turner         // at this point we have the correct amount of nibbles, or have run out of data to process.
869*c120c564SAndrew Turner         if(m_req_ts_nibbles == m_curr_ts_nibbles)
870*c120c564SAndrew Turner         {
871*c120c564SAndrew Turner             uint8_t new_bits = m_req_ts_nibbles * 4;
872*c120c564SAndrew Turner             if(m_curr_packet.getTSType() == STM_TS_GREY)
873*c120c564SAndrew Turner             {
874*c120c564SAndrew Turner                 uint64_t gray_val = bin_to_gray(m_curr_packet.getTSVal());
875*c120c564SAndrew Turner                 if(new_bits == 64)
876*c120c564SAndrew Turner                 {
877*c120c564SAndrew Turner                     gray_val = m_ts_update_value;
878*c120c564SAndrew Turner                 }
879*c120c564SAndrew Turner                 else
880*c120c564SAndrew Turner                 {
881*c120c564SAndrew Turner                     uint64_t mask = (0x1ULL << new_bits) - 1;
882*c120c564SAndrew Turner                     gray_val &= ~mask;
883*c120c564SAndrew Turner                     gray_val |= m_ts_update_value & mask;
884*c120c564SAndrew Turner                 }
885*c120c564SAndrew Turner                 m_curr_packet.setTS(gray_to_bin(gray_val),new_bits);
886*c120c564SAndrew Turner             }
887*c120c564SAndrew Turner             else if(m_curr_packet.getTSType() == STM_TS_NATBINARY)
888*c120c564SAndrew Turner             {
889*c120c564SAndrew Turner                 m_curr_packet.setTS(m_ts_update_value, new_bits);
890*c120c564SAndrew Turner             }
891*c120c564SAndrew Turner             else
892*c120c564SAndrew Turner                 throwBadSequenceError("STM: unknown timestamp encoding");
893*c120c564SAndrew Turner 
894*c120c564SAndrew Turner             sendPacket();
895*c120c564SAndrew Turner         }
896*c120c564SAndrew Turner     }
897*c120c564SAndrew Turner }
898*c120c564SAndrew Turner 
899*c120c564SAndrew Turner // pass in number of nibbles needed to extract the value
stmExtractVal8(uint8_t nibbles_to_val)900*c120c564SAndrew Turner void TrcPktProcStm::stmExtractVal8(uint8_t nibbles_to_val)
901*c120c564SAndrew Turner {
902*c120c564SAndrew Turner     bool bCont = true;
903*c120c564SAndrew Turner     while(bCont && (m_num_nibbles < nibbles_to_val))
904*c120c564SAndrew Turner     {
905*c120c564SAndrew Turner         bCont = readNibble();
906*c120c564SAndrew Turner         if(bCont)   // got a nibble
907*c120c564SAndrew Turner         {
908*c120c564SAndrew Turner             m_val8 <<= 4;
909*c120c564SAndrew Turner             m_val8 |= m_nibble;
910*c120c564SAndrew Turner         }
911*c120c564SAndrew Turner     }
912*c120c564SAndrew Turner }
913*c120c564SAndrew Turner 
stmExtractVal16(uint8_t nibbles_to_val)914*c120c564SAndrew Turner void TrcPktProcStm::stmExtractVal16(uint8_t nibbles_to_val)
915*c120c564SAndrew Turner {
916*c120c564SAndrew Turner     bool bCont = true;
917*c120c564SAndrew Turner     while(bCont && (m_num_nibbles < nibbles_to_val))
918*c120c564SAndrew Turner     {
919*c120c564SAndrew Turner         bCont = readNibble();
920*c120c564SAndrew Turner         if(bCont)   // got a nibble
921*c120c564SAndrew Turner         {
922*c120c564SAndrew Turner             m_val16 <<= 4;
923*c120c564SAndrew Turner             m_val16 |= m_nibble;
924*c120c564SAndrew Turner         }
925*c120c564SAndrew Turner     }
926*c120c564SAndrew Turner }
927*c120c564SAndrew Turner 
stmExtractVal32(uint8_t nibbles_to_val)928*c120c564SAndrew Turner void TrcPktProcStm::stmExtractVal32(uint8_t nibbles_to_val)
929*c120c564SAndrew Turner {
930*c120c564SAndrew Turner     bool bCont = true;
931*c120c564SAndrew Turner     while(bCont && (m_num_nibbles < nibbles_to_val))
932*c120c564SAndrew Turner     {
933*c120c564SAndrew Turner         bCont = readNibble();
934*c120c564SAndrew Turner         if(bCont)   // got a nibble
935*c120c564SAndrew Turner         {
936*c120c564SAndrew Turner             m_val32 <<= 4;
937*c120c564SAndrew Turner             m_val32 |= m_nibble;
938*c120c564SAndrew Turner         }
939*c120c564SAndrew Turner     }
940*c120c564SAndrew Turner }
941*c120c564SAndrew Turner 
stmExtractVal64(uint8_t nibbles_to_val)942*c120c564SAndrew Turner void TrcPktProcStm::stmExtractVal64(uint8_t nibbles_to_val)
943*c120c564SAndrew Turner {
944*c120c564SAndrew Turner     bool bCont = true;
945*c120c564SAndrew Turner     while(bCont && (m_num_nibbles < nibbles_to_val))
946*c120c564SAndrew Turner     {
947*c120c564SAndrew Turner         bCont = readNibble();
948*c120c564SAndrew Turner         if(bCont)   // got a nibble
949*c120c564SAndrew Turner         {
950*c120c564SAndrew Turner             m_val64 <<= 4;
951*c120c564SAndrew Turner             m_val64 |= m_nibble;
952*c120c564SAndrew Turner         }
953*c120c564SAndrew Turner     }
954*c120c564SAndrew Turner }
955*c120c564SAndrew Turner 
bin_to_gray(uint64_t bin_value)956*c120c564SAndrew Turner uint64_t TrcPktProcStm::bin_to_gray(uint64_t bin_value)
957*c120c564SAndrew Turner {
958*c120c564SAndrew Turner 	uint64_t gray_value = 0;
959*c120c564SAndrew Turner 	gray_value = (1ull << 63) & bin_value;
960*c120c564SAndrew Turner 	int i = 62;
961*c120c564SAndrew Turner 	for (; i >= 0; i--) {
962*c120c564SAndrew Turner 		uint64_t gray_arg_1 = ((1ull << (i+1)) & bin_value) >> (i+1);
963*c120c564SAndrew Turner 		uint64_t gray_arg_2 = ((1ull << i) & bin_value) >> i;
964*c120c564SAndrew Turner 		gray_value |= ((gray_arg_1 ^ gray_arg_2) << i);
965*c120c564SAndrew Turner 	}
966*c120c564SAndrew Turner 	return gray_value;
967*c120c564SAndrew Turner }
968*c120c564SAndrew Turner 
gray_to_bin(uint64_t gray_value)969*c120c564SAndrew Turner uint64_t TrcPktProcStm::gray_to_bin(uint64_t gray_value)
970*c120c564SAndrew Turner {
971*c120c564SAndrew Turner 	uint64_t bin_value = 0;
972*c120c564SAndrew Turner 	int bin_bit = 0;
973*c120c564SAndrew Turner 	for (; bin_bit < 64; bin_bit++) {
974*c120c564SAndrew Turner 		uint8_t bit_tmp = ((1ull << bin_bit) & gray_value) >> bin_bit;
975*c120c564SAndrew Turner 		uint8_t gray_bit = bin_bit + 1;
976*c120c564SAndrew Turner 		for (; gray_bit < 64; gray_bit++)
977*c120c564SAndrew Turner 			bit_tmp ^= (((1ull << gray_bit) & gray_value) >> gray_bit);
978*c120c564SAndrew Turner 
979*c120c564SAndrew Turner 		bin_value |= (bit_tmp << bin_bit);
980*c120c564SAndrew Turner 	}
981*c120c564SAndrew Turner 
982*c120c564SAndrew Turner 	return bin_value;
983*c120c564SAndrew Turner }
984*c120c564SAndrew Turner 
985*c120c564SAndrew Turner 
buildOpTables()986*c120c564SAndrew Turner void TrcPktProcStm::buildOpTables()
987*c120c564SAndrew Turner {
988*c120c564SAndrew Turner     // init all reserved
989*c120c564SAndrew Turner     for(int i = 0; i < 0x10; i++)
990*c120c564SAndrew Turner     {
991*c120c564SAndrew Turner         m_1N_ops[i] = &TrcPktProcStm::stmPktReserved;
992*c120c564SAndrew Turner         m_2N_ops[i] = &TrcPktProcStm::stmPktReservedFn;
993*c120c564SAndrew Turner         m_3N_ops[i] = &TrcPktProcStm::stmPktReservedF0n;
994*c120c564SAndrew Turner     }
995*c120c564SAndrew Turner 
996*c120c564SAndrew Turner     // set the 1N operations
997*c120c564SAndrew Turner     m_1N_ops[0x0] = &TrcPktProcStm::stmPktNull;
998*c120c564SAndrew Turner     m_1N_ops[0x1] = &TrcPktProcStm::stmPktM8;
999*c120c564SAndrew Turner     m_1N_ops[0x2] = &TrcPktProcStm::stmPktMERR;
1000*c120c564SAndrew Turner     m_1N_ops[0x3] = &TrcPktProcStm::stmPktC8;
1001*c120c564SAndrew Turner     m_1N_ops[0x4] = &TrcPktProcStm::stmPktD8;
1002*c120c564SAndrew Turner     m_1N_ops[0x5] = &TrcPktProcStm::stmPktD16;
1003*c120c564SAndrew Turner     m_1N_ops[0x6] = &TrcPktProcStm::stmPktD32;
1004*c120c564SAndrew Turner     m_1N_ops[0x7] = &TrcPktProcStm::stmPktD64;
1005*c120c564SAndrew Turner     m_1N_ops[0x8] = &TrcPktProcStm::stmPktD8MTS;
1006*c120c564SAndrew Turner     m_1N_ops[0x9] = &TrcPktProcStm::stmPktD16MTS;
1007*c120c564SAndrew Turner     m_1N_ops[0xA] = &TrcPktProcStm::stmPktD32MTS;
1008*c120c564SAndrew Turner     m_1N_ops[0xB] = &TrcPktProcStm::stmPktD64MTS;
1009*c120c564SAndrew Turner     m_1N_ops[0xC] = &TrcPktProcStm::stmPktD4;
1010*c120c564SAndrew Turner     m_1N_ops[0xD] = &TrcPktProcStm::stmPktD4MTS;
1011*c120c564SAndrew Turner     m_1N_ops[0xE] = &TrcPktProcStm::stmPktFlagTS;
1012*c120c564SAndrew Turner     m_1N_ops[0xF] = &TrcPktProcStm::stmPktFExt;
1013*c120c564SAndrew Turner 
1014*c120c564SAndrew Turner     // set the 2N operations 0xFn
1015*c120c564SAndrew Turner     m_2N_ops[0x0] = &TrcPktProcStm::stmPktF0Ext;
1016*c120c564SAndrew Turner     // 0x1 unused in CS STM
1017*c120c564SAndrew Turner     m_2N_ops[0x2] = &TrcPktProcStm::stmPktGERR;
1018*c120c564SAndrew Turner     m_2N_ops[0x3] = &TrcPktProcStm::stmPktC16;
1019*c120c564SAndrew Turner     m_2N_ops[0x4] = &TrcPktProcStm::stmPktD8TS;
1020*c120c564SAndrew Turner     m_2N_ops[0x5] = &TrcPktProcStm::stmPktD16TS;
1021*c120c564SAndrew Turner     m_2N_ops[0x6] = &TrcPktProcStm::stmPktD32TS;
1022*c120c564SAndrew Turner     m_2N_ops[0x7] = &TrcPktProcStm::stmPktD64TS;
1023*c120c564SAndrew Turner     m_2N_ops[0x8] = &TrcPktProcStm::stmPktD8M;
1024*c120c564SAndrew Turner     m_2N_ops[0x9] = &TrcPktProcStm::stmPktD16M;
1025*c120c564SAndrew Turner     m_2N_ops[0xA] = &TrcPktProcStm::stmPktD32M;
1026*c120c564SAndrew Turner     m_2N_ops[0xB] = &TrcPktProcStm::stmPktD64M;
1027*c120c564SAndrew Turner     m_2N_ops[0xC] = &TrcPktProcStm::stmPktD4TS;
1028*c120c564SAndrew Turner     m_2N_ops[0xD] = &TrcPktProcStm::stmPktD4M;
1029*c120c564SAndrew Turner     m_2N_ops[0xE] = &TrcPktProcStm::stmPktFlag;
1030*c120c564SAndrew Turner     m_2N_ops[0xF] = &TrcPktProcStm::stmPktASync;
1031*c120c564SAndrew Turner 
1032*c120c564SAndrew Turner     // set the 3N operations 0xF0n
1033*c120c564SAndrew Turner     m_3N_ops[0x0] = &TrcPktProcStm::stmPktVersion;
1034*c120c564SAndrew Turner     m_3N_ops[0x1] = &TrcPktProcStm::stmPktNullTS;
1035*c120c564SAndrew Turner     // 0x2 .. 0x5 not used by CS STM
1036*c120c564SAndrew Turner     m_3N_ops[0x6] = &TrcPktProcStm::stmPktTrigger;
1037*c120c564SAndrew Turner     m_3N_ops[0x7] = &TrcPktProcStm::stmPktTriggerTS;
1038*c120c564SAndrew Turner     m_3N_ops[0x8] = &TrcPktProcStm::stmPktFreq;
1039*c120c564SAndrew Turner     // 0x9 .. 0xF not used by CS STM
1040*c120c564SAndrew Turner 
1041*c120c564SAndrew Turner }
1042*c120c564SAndrew Turner 
1043*c120c564SAndrew Turner /* End of File trc_pkt_proc_stm.cpp */
1044