+ // Read the RCU trailer
+ // This includes the trailer size,
+ // RCU identifier and raw data payload.
+ // The RCU trailer format is described
+ // in details in the RCU manual.
+
+ // We use the last word of the payload
+ // in order to decide which RCU firmware
+ // was used during the data taking.
+ // The firmware v2 adds 0xAAAA as 16
+ // most significant bits and since the
+ // payload size (firmware v1) can not be
+ // that big, we use this as a unique
+ // label of the firmware version.
+
+ Int_t index = fRawReader->GetDataSize();
+ UInt_t word = Get32bitWord(index);
+ if (((word >> 16) == 0xaaaa) || (word == 2)) {
+ // This is RCU formware v2
+ // The statement word==2 is needed only temporary
+ // in order to be able to read previously generated
+ // aliroot raw data
+
+ Int_t trailerSize = 0;
+ if (word == 2) {
+ AliInfo("Old simulated raw data is assumed!");
+ trailerSize = 2;
+ fRCUId = 0;
+ }
+ else {
+ // First read 32-bit word with the
+ // trailer size (7 bits), RCU ID (9 bits) and
+ // 0xAAA (the rest - 16 bits)
+ fRCUId = (Int_t)((word >> 7) & 0x1ff);
+ trailerSize = (word & 0x7F);
+ }
+
+ // Now read the beginning of the trailer
+ // where the payload size is written
+ if (trailerSize < 2) {
+ fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d bytes",
+ trailerSize*4));
+ AliWarning(Form("Invalid trailer size found (%d bytes) !",
+ trailerSize*4));
+ }
+
+ Int_t position = ReadRCUTrailer(index,trailerSize);
+ if (fRawReader->GetType() != AliRawEventHeaderBase::kStartOfData) {
+ // The size is specified in a number of 40bits
+ // Therefore we need to transform it to number of bytes
+ position *= 5;
+
+ // Check the consistency of the header and trailer
+ if (((fRawReader->GetDataSize() - trailerSize*4) < position) ||
+ ((fRawReader->GetDataSize() - trailerSize*4) >= (position + 4))) {
+ fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d tr=%d rcu=%d bytes",
+ fRawReader->GetDataSize(),
+ trailerSize*4,
+ position));
+ AliWarning(Form("Inconsistent raw data size ! Raw data size - %d bytes (from the header), RCU trailer - %d bytes, raw data paylod - %d bytes !",
+ fRawReader->GetDataSize(),
+ trailerSize*4,
+ position));
+ position = fRawReader->GetDataSize() - trailerSize*4;
+ }
+
+ return position * 8 / 10;
+ }
+ else {
+ // Special RCU payload in case of SOD events
+ // The decoding is left to the user code
+ // Here we just retrieve the payload size
+ return position;
+ }
+ }
+ else {
+ // In case of the Old RCU trailer format
+ // we have to read just the size of altro payload
+ // in units of 40-bit words
+ Int_t position = (Int_t)word;
+
+ fRCUId = -1;
+ fRCUTrailerSize = 0;
+ fRCUTrailerData = NULL;
+
+ // The size is specified in a number of 40bits
+ // Therefore we need to transform it to number of bytes
+ position *= 5;
+
+ if (!fIsShortDataHeader) {
+
+ // Check the consistency of the header and trailer
+ if (((fRawReader->GetDataSize() - 4) < position) ||
+ ((fRawReader->GetDataSize() - 4) >= (position + 4))) {
+ fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
+ fRawReader->GetDataSize()-4,
+ position));
+ // PrintDebug();
+ AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
+ fRawReader->GetDataSize()-4,
+ position));
+ position = fRawReader->GetDataSize()-4;
+ }
+ }
+ else {
+ // Check the consistency of the header and trailer
+ // In this case the header is shorter by 4 bytes
+ if ((fRawReader->GetDataSize() < position) ||
+ (fRawReader->GetDataSize() >= (position + 4))) {
+ fRawReader->AddMajorErrorLog(kRCUTrailerSizeErr,Form("h=%d rcu=%d bytes",
+ fRawReader->GetDataSize(),
+ position));
+ // PrintDebug();
+ AliWarning(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
+ fRawReader->GetDataSize(),
+ position));
+ position = fRawReader->GetDataSize();
+ }
+
+ // 7 32-bit words Common Data Header
+ // therefore we have to shift back by 4 bytes
+ // the pointer to the raw data payload
+ fData -= 4;
+ }
+
+ // Return the position in units of 10-bit words
+ return position*8/10;
+ }
+}
+
+//_____________________________________________________________________________
+UInt_t AliAltroRawStream::Get32bitWord(Int_t &index)
+{
+ // This method returns the 32 bit word at a given
+ // position inside the raw data payload.
+ // The 'index' points to the beginning of the next word.
+ // The method is supposed to be endian (platform)
+ // independent.
+ if (!fData) {
+ PrintDebug();
+ AliFatal("Raw data paylod buffer is not yet initialized !");
+ }
+
+ if (index < 4) {
+ fRawReader->AddFatalErrorLog(k32bitWordReadErr,Form("pos = %d",index));
+ // PrintDebug();
+ AliWarning(Form("Invalid raw data payload position (%d) !",index));
+ }
+
+ UInt_t word = 0;
+ word = fData[--index] << 24;
+ word |= fData[--index] << 16;
+ word |= fData[--index] << 8;
+ word |= fData[--index];
+
+ return word;
+}
+
+//_____________________________________________________________________________
+Int_t AliAltroRawStream::ReadRCUTrailer(Int_t &index, Int_t trailerSize)
+{
+ // The method decodes the RCU trailer data
+ // according to the RCU fw ver.2 specs
+
+ fRCUTrailerSize = trailerSize*4;
+
+ for (trailerSize -= 2; trailerSize > 0; trailerSize--) {
+ Int_t word = Get32bitWord(index);
+ Int_t parCode = word >> 26;
+ Int_t parData = word & 0x3FFFFFF;
+ switch (parCode) {
+ case 1:
+ // ERR_REG1
+ fFECERRA = ((parData >> 13) & 0x1FFF) << 7;
+ fFECERRB = ((parData & 0x1FFF)) << 7;
+ break;
+ case 2:
+ // ERR_REG2
+ fERRREG2 = parData & 0x1FF;
+ break;
+ case 3:
+ // ERR_REG3
+ fERRREG3 = parData & 0xFFF;
+ break;
+ case 4:
+ // ERR_REG4
+ fERRREG4 = parData & 0xFFF;
+ break;
+ case 5:
+ // FEC_RO_A
+ fActiveFECsA = parData & 0xFFFF;
+ break;
+ case 6:
+ // FEC_RO_B
+ fActiveFECsB = parData & 0xFFFF;
+ break;
+ case 7:
+ // RDO_CFG1
+ fAltroCFG1 = parData & 0xFFFFF;
+ break;
+ case 8:
+ // RDO_CFG2
+ fAltroCFG2 = parData & 0x1FFFFFF;
+ break;
+ default:
+ fRawReader->AddMinorErrorLog(kRCUTrailerErr,"undef word");
+ AliWarning(Form("Undefined parameter code %d, ignore it !",
+ parCode));
+ break;
+ }
+ }
+
+ if (index < 4) {
+ fRawReader->AddMajorErrorLog(kRCUTrailerErr,Form("tr=%d raw=%d bytes",
+ fRCUTrailerSize,
+ fRawReader->GetDataSize()));
+ AliWarning(Form("Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%d bytes)!",
+ fRCUTrailerSize,
+ fRawReader->GetDataSize()));
+ }
+ fRCUTrailerData = fData + index;
+
+ Int_t position = Get32bitWord(index);
+