xref: /titanic_44/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_crc.c (revision d4b0f84707225327c617c6838361d3cfb7762b34)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2000 by Cisco Systems, Inc.  All rights reserved.
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * This file contains CRC-32C code use to verify
27  * iSCSI HeaderDigests and DataDigests.
28  */
29 
30 #include <sys/types.h>	/* standard types */
31 #include "iscsi.h"	/* contains prototypes */
32 #include <hd_crc.h>
33 
34 /*
35  * This is the CRC-32C table
36  * Generated with:
37  * width = 32 bits
38  * poly = 0x1EDC6F41
39  * reflect input bytes = true
40  * reflect output bytes = true
41  */
42 
43 uint32_t iscsi_crc32c_table[256] =
44 {
45 	0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
46 	0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
47 	0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
48 	0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
49 	0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
50 	0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
51 	0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
52 	0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
53 	0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
54 	0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
55 	0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
56 	0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
57 	0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
58 	0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
59 	0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
60 	0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
61 	0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
62 	0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
63 	0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
64 	0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
65 	0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
66 	0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
67 	0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
68 	0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
69 	0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
70 	0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
71 	0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
72 	0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
73 	0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
74 	0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
75 	0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
76 	0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
77 	0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
78 	0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
79 	0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
80 	0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
81 	0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
82 	0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
83 	0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
84 	0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
85 	0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
86 	0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
87 	0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
88 	0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
89 	0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
90 	0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
91 	0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
92 	0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
93 	0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
94 	0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
95 	0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
96 	0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
97 	0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
98 	0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
99 	0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
100 	0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
101 	0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
102 	0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
103 	0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
104 	0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
105 	0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
106 	0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
107 	0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
108 	0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
109 };
110 
111 /*
112  * -1 - uninitialized
113  * 0  - applicable
114  * others - NA
115  */
116 static int iscsi_crc32_hd = -1;
117 
118 /*
119  * iscsi_crc32c - Steps through buffer one byte at at time, calculates
120  * reflected crc using table.
121  */
122 uint32_t
iscsi_crc32c(void * address,unsigned long length)123 iscsi_crc32c(void *address, unsigned long length)
124 {
125 	uint8_t *buffer = address;
126 	uint32_t crc = 0xffffffff, result;
127 #ifdef _BIG_ENDIAN
128 	uint8_t byte0, byte1, byte2, byte3;
129 #endif
130 
131 	if (iscsi_crc32_hd == -1) {
132 		if (hd_crc32_avail((uint32_t *)iscsi_crc32c_table) == B_TRUE) {
133 			iscsi_crc32_hd = 0;
134 		} else {
135 			iscsi_crc32_hd = 1;
136 		}
137 	}
138 	if (iscsi_crc32_hd == 0)
139 		return (HW_CRC32(buffer, length, crc));
140 
141 	ASSERT(address != NULL);
142 
143 	while (length--) {
144 		crc = iscsi_crc32c_table[(crc ^ *buffer++) & 0xFFL] ^
145 		    (crc >> 8);
146 	}
147 	result = crc ^ 0xffffffff;
148 
149 #ifdef	_BIG_ENDIAN
150 	byte0 = (uint8_t)(result & 0xFF);
151 	byte1 = (uint8_t)((result >> 8) & 0xFF);
152 	byte2 = (uint8_t)((result >> 16) & 0xFF);
153 	byte3 = (uint8_t)((result >> 24) & 0xFF);
154 	result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
155 #endif	/* _BIG_ENDIAN */
156 
157 	return (result);
158 }
159 
160 
161 /*
162  * iscsi_crc32c_continued - Continues stepping through buffer one
163  * byte at at time, calculates reflected crc using table.
164  */
165 uint32_t
iscsi_crc32c_continued(void * address,unsigned long length,uint32_t crc)166 iscsi_crc32c_continued(void *address, unsigned long length, uint32_t crc)
167 {
168 	uint8_t *buffer = address;
169 	uint32_t result;
170 #ifdef	_BIG_ENDIAN
171 	uint8_t byte0, byte1, byte2, byte3;
172 #endif
173 
174 	if (iscsi_crc32_hd == -1) {
175 		if (hd_crc32_avail((uint32_t *)iscsi_crc32c_table) == B_TRUE) {
176 			iscsi_crc32_hd = 0;
177 		} else {
178 			iscsi_crc32_hd = 1;
179 		}
180 	}
181 	if (iscsi_crc32_hd == 0)
182 		return (HW_CRC32_CONT(buffer, length, crc));
183 
184 	ASSERT(address != NULL);
185 
186 #ifdef	_BIG_ENDIAN
187 	byte0 = (uint8_t)((crc >> 24) & 0xFF);
188 	byte1 = (uint8_t)((crc >> 16) & 0xFF);
189 	byte2 = (uint8_t)((crc >> 8) & 0xFF);
190 	byte3 = (uint8_t)(crc & 0xFF);
191 	crc = ((byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0);
192 #endif
193 
194 	crc = crc ^ 0xffffffff;
195 	while (length--) {
196 		crc = iscsi_crc32c_table[(crc ^ *buffer++) & 0xFFL] ^
197 		    (crc >> 8);
198 	}
199 	result = crc ^ 0xffffffff;
200 
201 #ifdef	_BIG_ENDIAN
202 	byte0 = (uint8_t)(result & 0xFF);
203 	byte1 = (uint8_t)((result >> 8) & 0xFF);
204 	byte2 = (uint8_t)((result >> 16) & 0xFF);
205 	byte3 = (uint8_t)((result >> 24) & 0xFF);
206 	result = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
207 #endif
208 	return (result);
209 }
210