summaryrefslogtreecommitdiffstats
path: root/clib/ecc.h
blob: c6f67f7cdc02df818e1002d4b02da050b8743dab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
86
87
88
89
90
91
92
93
94
95
96
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/*
 * Copyright (c) International Business Machines Corp., 2014
 *
 * 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 2 of the License, or
 * (at your option) any later version.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

/*!
 * @file ecc.h
 * @brief FSP-2 & P8 ECC functions
 * @details These functions are used to insert and remove FSP-2 & P8 ECC
 *          bytes. 8-bits of ECC is inserted every 8 bytes of data such as:
 *          XXxxXXxxXXxxXXxxYY (where XXxx is 4 nibbles of data and YY is
 *          2 nibbles of ECC)
 * @author Shaun Wetzstein <shaun@us.ibm.com>
 * @date 2011
 */

#ifndef __ECC_H__
#define __ECC_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
/** Status for the ECC removal function. */
enum ecc_status
    {
      CLEAN=0,          //< No ECC Error was detected.
      CORRECTED=1,      //< ECC error detected and corrected.
      UNCORRECTABLE=2   //< ECC error detected and uncorrectable.
    };
typedef enum  ecc_status ecc_status_t;

enum ecc_bitfields
    {
        GD = 0xff,      //< Good, ECC matches.
        UE = 0xfe,      //< Uncorrectable.
        E0 = 71,        //< Error in ECC bit 0
        E1 = 70,        //< Error in ECC bit 1
        E2 = 69,        //< Error in ECC bit 2
        E3 = 68,        //< Error in ECC bit 3
        E4 = 67,        //< Error in ECC bit 4
        E5 = 66,        //< Error in ECC bit 5
        E6 = 65,        //< Error in ECC bit 6
        E7 = 64         //< Error in ECC bit 7
    };

/*!
 * @brief Compute the 8-bit ECC (SFC) value given an array of 8
 *        unsigned char data values
 * @param data [in] Input data
 * @return 8-bit SFC ECC value
 */
	extern uint8_t sfc_ecc(uint8_t __data[8]);

/*!
 * @brief Copy bytes from the source buffer to the destination buffer while
 *        computing and injecting an 8-bit SFC ECC value for every 8-bytes
 *        of source buffer read
 * @param __dst [in] Destination buffer
 * @param __dst_sz [in] Destination buffer size (in bytes) which must be large
 *        enough to store both the data and the ECC bytes
 * @param __src [in] Source buffer
 * @param __src_sz [in] Source buffer size (in bytes) which must be a multiple
 *        of 8 bytes
 * @return -1 if an error occurs, number of bytes copied (including ECC bytes)
 *         otherwise.
 *         EINVAL if __src_sz is 0 or not a multiple of 8 bytes
 *         ENOBUFS if __dst_sz is not large enough to store the ECC bytes
 *
 */
	extern ssize_t sfc_ecc_inject(void *__restrict __dst, size_t __dst_sz,
				      const void *__restrict __src,
				      size_t __src_sz)
/*! @cond */
	 __nonnull((1, 3)) /*! @endcond */ ;

/*!
 * @brief Copy bytes from the source buffer to the destination buffer while
 *        computing and removing an 8-bit SFC ECC value for every 9-bytes
 *        of source buffer read
 * @param __dst [in] Destination buffer
 * @param __dst_sz [in] Destination buffer size (in bytes) which must be large
 *        enough to store the data (after ECC removal)
 * @param __src [in] Source buffer
 * @param __src_sz [in] Source buffer size (in bytes) which must be a multiple
 *        9 bytes
 * @return -1 if an error occurs, number of bytes copied (excluding ECC bytes)
 *         otherwise.  if an ECC mismatch error occurs the function returns
 *         immediately and the return code indicates the number of bytes processed
 *         prior to the ECC error.
 *         EINVAL if __src_sz is 0 or not a multiple of 9 bytes
 *         ENOBUFS if __dst_sz is not large enough to store the ECC bytes
 */
	extern ssize_t sfc_ecc_remove(void *__restrict __dst, size_t __dst_sz,
				      const void *__restrict __src,
				      size_t __src_sz)
/*! @cond */
	 __nonnull((1, 3)) /*! @endcond */ ;

/*!
 * @brief Hexdump the contents of a memory buffer to an output stream.
 *        This is a buck-standard hexdump except it issolates the ECC value
 *        in a separate column for easy debug.
 * @param __out [in] Output stream
 * @param __addr [in] Starting put to display (in bytes)
 * @param __buf [in] Data buffer
 * @param __buf_sz [in] Data buffer size (in bytes)
 * @return -1 if an error occurs, number of bytes copied (excluding ECC bytes)
 *         otherwise.  if an ECC mismatch error occurs the function highlights the
 *         the corrupted data with red ANSI.
 */
	extern void sfc_ecc_dump(FILE * __out, uint32_t __addr,
				 void *__restrict __buf, size_t __buf_sz)
/*! @cond */
	 __nonnull((1, 3)) /*! @endcond */ ;

/*!
 * @brief Copy bytes from the source buffer to the destination buffer while
 *        computing and injecting an 8-bit P8 ECC value for every 8-bytes
 *        of source buffer read
 * @param __dst [in] Destination buffer
 * @param __dst_sz [in] Destination buffer size (in bytes) which must be large
 *        enough to store both the data and the ECC bytes
 * @param __src [in] Source buffer
 * @param __src_sz [in] Source buffer size (in bytes) which must be a multiple
 *        of 8 bytes
 * @return -1 if an error occurs, number of bytes copied (including ECC bytes)
 *         otherwise.
 *         EINVAL if __src_sz is 0 or not a multiple of 8 bytes
 *         ENOBUFS if __dst_sz is not large enough to store the ECC bytes
 *
 */
	extern ssize_t p8_ecc_inject(void *__restrict __dst, size_t __dst_sz,
				     const void *__restrict __src,
				     size_t __src_sz)
/*! @cond */
	 __nonnull((1, 3)) /*! @endcond */ ;

/*!
 * @brief Copy bytes from the source buffer to the destination buffer while
 *        computing and removing an 8-bit P8 ECC value for every 9-bytes
 *        of source buffer read
 * @param __dst [in] Destination buffer
 * @param __dst_sz [in] Destination buffer size (in bytes) which must be large
 *        enough to store the data (after ECC removal)
 * @param __src [in] Source buffer
 * @param __src_sz [in] Source buffer size (in bytes) which must be a multiple
 *        9 bytes
 * @return 0 - CLEAN for success
 *         1 - CORRECTED error - _src [in] buffer changed
 *         2 - UNCORRECTABLE error.
 */
  extern ecc_status_t p8_ecc_remove(void *__restrict __dst, size_t __dst_sz,
				     void *__restrict __src,
				     size_t __src_sz)

/*! @cond */
	 __nonnull((1, 3)) /*! @endcond */ ;

/*!
 * @brief Copy bytes from the source buffer to the destination buffer while
 *        computing and removing an 8-bit P8 ECC value for every 9-bytes
 *        of source buffer read
 * @param __dst [in] Destination buffer
 * @param __dst_sz [in] Destination buffer size (in bytes) which must be large
 *        enough to store the data (after ECC removal)
 * @param __src [in] Source buffer
 * @param __src_sz [in] Source buffer size (in bytes) which must be a multiple
 *        9 bytes
 * @return -1 if an error occurs, number of bytes copied (excluding ECC bytes)
 *         otherwise.  if an ECC mismatch error occurs the function returns
 *         immediately and the return code indicates zero number of bytes
 *         processed
 *         EINVAL if __src_sz is 0 or not a multiple of 9 bytes
 *         ENOBUFS if __dst_sz is not large enough to store the ECC bytes
 */
  extern ssize_t p8_ecc_remove_size(void *__restrict __dst, size_t __dst_sz,
				     void *__restrict __src, size_t __src_sz)

/*! @cond */
	 __nonnull((1, 3)) /*! @endcond */ ;

/*!
 * @brief Hexdump the contents of a memory buffer to an output stream.
 *        This is a buck-standard hexdump except it issolates the P8 ECC
 *        value in a separate column for easy debug.
 * @param __out [in] Output stream
 * @param __addr [in] Starting put to display (in bytes)
 * @param __buf [in] Data buffer
 * @param __buf_sz [in] Data buffer size (in bytes)
 * @return -1 if an error occurs, number of bytes copied (excluding ECC bytes)
 *         otherwise.  if an ECC mismatch error occurs the function highlights the
 *         the corrupted data with red ANSI.
 */
	extern void p8_ecc_dump(FILE * __out, uint32_t __addr,
				void *__restrict __buf, size_t __buf_sz)
/*! @cond */
	 __nonnull((1, 3)) /*! @endcond */ ;

#ifdef __cplusplus
}
#endif
#endif				/* __ECC_H__ */
OpenPOWER on IntegriCloud