CRC.hpp 4.75 KB
Newer Older
1
/*
2
 * @project        The CERN Tape Archive (CTA)
3
 * @copyright      Copyright(C) 2015-2021 CERN
4
5
6
7
 * @license        This program is free software: you can redistribute it and/or modify
 *                 it under the terms of the GNU General Public License as published by
 *                 the Free Software Foundation, either version 3 of the License, or
 *                 (at your option) any later version.
8
 *
9
10
11
12
 *                 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 more details.
13
 *
14
15
 *                 You should have received a copy of the GNU General Public License
 *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
 */
17
18
19
20
21

#pragma once

#include <stdint.h>

22
23
namespace cta {

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/**
 * Set of CRC functions.
 */ 
  
/**
 * Compute by software Reed Solomon CRC for the given block.
 *
 * @param crcInit  The initial crc (0 for fresh) (i.e., seed).
 * @param cnt      The number of data bytes to compute CRC for.
 * @param start    The starting address of the data bytes (e.g., data buffer).
 * @return The computed CRC in big endian (MSB is first byte).
 */

uint32_t crcRS_sw (const uint32_t crcInit, const uint32_t cnt, 
  const void *const start);
  
/**
 * Compute by software CRC32C (iSCSI) for the given block.
 *
 * @param crcInit  The initial crc (0xFFFFFFFF for fresh) (i.e., seed).
 * @param cnt      The number of data bytes to compute CRC for.
 * @param start    The starting address of the data bytes (e.g., data buffer).
 * @return The computed CRC in big endian (MSB is first byte). 
 */
uint32_t crc32c_sw (const uint32_t crcInit, const uint32_t cnt, 
  const void *const start);

/**
 * Compute by hardware CRC32C (iSCSI) for the given block.
 *
 * CRC32 Generator Polynomial:
 * 0x11EDC6F41
 * x^32+x^28+x^27+x^26+x^25+x^23+x^22+x^20+x^19+x^18+x^14+x^13+x^11+
 * x^10+x^9+x^8+x^6+x^0
 *
 * @param crcInit  The initial crc (0xFFFFFFFF for fresh) (i.e., seed).
 * @param cnt      The number of data bytes to compute CRC for.
 * @param start    The starting address of the data bytes (e.g., data buffer).
 * @return The computed CRC in big endian (MSB is first byte). 
 */
uint32_t crc32c_hw (const uint32_t crcInit, const uint32_t cnt, 
  const void *const start);

/**
 * Check for SSE 4.2.  SSE 4.2 was first supported in Nehalem processors
 * introduced in November, 2008.  This does not check for the existence of the
 * cpuid instruction itself, which was introduced on the 486SL in 1992, so this
 * will fail on earlier x86 processors.  cpuid works on all Pentium and later
 * processors. 
 */
#define SSE42(have) \
  do { \
      uint32_t eax, ecx; \
      eax = 1; \
      __asm__("cpuid" \
              : "=c"(ecx) \
              : "a"(eax) \
              : "%ebx", "%edx"); \
      (have) = (ecx >> 20) & 1; \
  } while (0)

/**
86
87
 * Compute the CRC32C (iSCSI). If the crc32 processor's instruction is
 * available than use the hardware version. Otherwise use the software version.
88
89
90
91
92
93
94
95
96
 *
 * @param crcInit  The initial crc (0xFFFFFFFF for fresh) (i.e., seed).
 * @param cnt      The number of data bytes to compute CRC for.
 * @param start    The starting address of the data bytes (e.g., data buffer).
 * @return The computed CRC in big endian (MSB is first byte). 
 */
uint32_t crc32c(const uint32_t crcInit, const uint32_t cnt, 
  const void *const start);

97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/**
 * Compute the CRC32C (iSCSI) and append it to the memory block.
 * If the crc32 processor's instruction is available
 * use the hardware version. Otherwise use the software version.
 *
 * @param crcInit  The initial crc (0xFFFFFFFF for fresh) (i.e., seed).
 * @param cnt      The number of data bytes in the memory block.
 * @param start    The starting address of the data bytes (e.g., data buffer).
 *                 The memory block must be big enough to save additional
 *                 4 bytes at the end.
 * @return The length of the memory block with crc32c added.
 */
uint32_t addCrc32cToMemoryBlock(const uint32_t crcInit,
  const uint32_t cnt, uint8_t *start);

/**
 * Compute the CRC32C (iSCSI) and check it for the memory block with CRC32C
 * addition. If the crc32 processor's instruction is available
 * use the hardware version. Otherwise use the software version.
 *
 * @param crcInit  The initial crc (0xFFFFFFFF for fresh) (i.e., seed).
 * @param cnt      The number of data bytes in the memory block.
 * @param start    The starting address of the data bytes (e.g., data buffer).
 * @return True if CRC32C is correct and False otherwise.
 */
bool verifyCrc32cForMemoryBlockWithCrc32c(
  const uint32_t crcInit, const uint32_t cnt, const uint8_t *start);

125
126

} // namespace cta