[PATCH] ppc32: #ifdef out ALTIVEC specific code in __switch_to
[linux-2.6] / drivers / s390 / crypto / z90hardware.c
1 /*
2  *  linux/drivers/s390/crypto/z90hardware.c
3  *
4  *  z90crypt 1.3.2
5  *
6  *  Copyright (C)  2001, 2004 IBM Corporation
7  *  Author(s): Robert Burroughs (burrough@us.ibm.com)
8  *             Eric Rossman (edrossma@us.ibm.com)
9  *
10  *  Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2, or (at your option)
15  * any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  */
26
27 #include <asm/uaccess.h>
28 #include <linux/compiler.h>
29 #include <linux/delay.h>
30 #include <linux/init.h>
31 #include <linux/module.h>
32 #include "z90crypt.h"
33 #include "z90common.h"
34
35 #define VERSION_Z90HARDWARE_C "$Revision: 1.34 $"
36
37 char z90hardware_version[] __initdata =
38         "z90hardware.o (" VERSION_Z90HARDWARE_C "/"
39                           VERSION_Z90COMMON_H "/" VERSION_Z90CRYPT_H ")";
40
41 struct cca_token_hdr {
42         unsigned char  token_identifier;
43         unsigned char  version;
44         unsigned short token_length;
45         unsigned char  reserved[4];
46 };
47
48 #define CCA_TKN_HDR_ID_EXT 0x1E
49
50 struct cca_private_ext_ME_sec {
51         unsigned char  section_identifier;
52         unsigned char  version;
53         unsigned short section_length;
54         unsigned char  private_key_hash[20];
55         unsigned char  reserved1[4];
56         unsigned char  key_format;
57         unsigned char  reserved2;
58         unsigned char  key_name_hash[20];
59         unsigned char  key_use_flags[4];
60         unsigned char  reserved3[6];
61         unsigned char  reserved4[24];
62         unsigned char  confounder[24];
63         unsigned char  exponent[128];
64         unsigned char  modulus[128];
65 };
66
67 #define CCA_PVT_USAGE_ALL 0x80
68
69 struct cca_public_sec {
70         unsigned char  section_identifier;
71         unsigned char  version;
72         unsigned short section_length;
73         unsigned char  reserved[2];
74         unsigned short exponent_len;
75         unsigned short modulus_bit_len;
76         unsigned short modulus_byte_len;
77         unsigned char  exponent[3];
78 };
79
80 struct cca_private_ext_ME {
81         struct cca_token_hdr          pvtMEHdr;
82         struct cca_private_ext_ME_sec pvtMESec;
83         struct cca_public_sec         pubMESec;
84 };
85
86 struct cca_public_key {
87         struct cca_token_hdr  pubHdr;
88         struct cca_public_sec pubSec;
89 };
90
91 struct cca_pvt_ext_CRT_sec {
92         unsigned char  section_identifier;
93         unsigned char  version;
94         unsigned short section_length;
95         unsigned char  private_key_hash[20];
96         unsigned char  reserved1[4];
97         unsigned char  key_format;
98         unsigned char  reserved2;
99         unsigned char  key_name_hash[20];
100         unsigned char  key_use_flags[4];
101         unsigned short p_len;
102         unsigned short q_len;
103         unsigned short dp_len;
104         unsigned short dq_len;
105         unsigned short u_len;
106         unsigned short mod_len;
107         unsigned char  reserved3[4];
108         unsigned short pad_len;
109         unsigned char  reserved4[52];
110         unsigned char  confounder[8];
111 };
112
113 #define CCA_PVT_EXT_CRT_SEC_ID_PVT 0x08
114 #define CCA_PVT_EXT_CRT_SEC_FMT_CL 0x40
115
116 struct cca_private_ext_CRT {
117         struct cca_token_hdr       pvtCrtHdr;
118         struct cca_pvt_ext_CRT_sec pvtCrtSec;
119         struct cca_public_sec      pubCrtSec;
120 };
121
122 struct ap_status_word {
123         unsigned char q_stat_flags;
124         unsigned char response_code;
125         unsigned char reserved[2];
126 };
127
128 #define AP_Q_STATUS_EMPTY               0x80
129 #define AP_Q_STATUS_REPLIES_WAITING     0x40
130 #define AP_Q_STATUS_ARRAY_FULL          0x20
131
132 #define AP_RESPONSE_NORMAL              0x00
133 #define AP_RESPONSE_Q_NOT_AVAIL         0x01
134 #define AP_RESPONSE_RESET_IN_PROGRESS   0x02
135 #define AP_RESPONSE_DECONFIGURED        0x03
136 #define AP_RESPONSE_CHECKSTOPPED        0x04
137 #define AP_RESPONSE_BUSY                0x05
138 #define AP_RESPONSE_Q_FULL              0x10
139 #define AP_RESPONSE_NO_PENDING_REPLY    0x10
140 #define AP_RESPONSE_INDEX_TOO_BIG       0x11
141 #define AP_RESPONSE_NO_FIRST_PART       0x13
142 #define AP_RESPONSE_MESSAGE_TOO_BIG     0x15
143
144 #define AP_MAX_CDX_BITL         4
145 #define AP_RQID_RESERVED_BITL   4
146 #define SKIP_BITL               (AP_MAX_CDX_BITL + AP_RQID_RESERVED_BITL)
147
148 struct type4_hdr {
149         unsigned char  reserved1;
150         unsigned char  msg_type_code;
151         unsigned short msg_len;
152         unsigned char  request_code;
153         unsigned char  msg_fmt;
154         unsigned short reserved2;
155 };
156
157 #define TYPE4_TYPE_CODE 0x04
158 #define TYPE4_REQU_CODE 0x40
159
160 #define TYPE4_SME_LEN 0x0188
161 #define TYPE4_LME_LEN 0x0308
162 #define TYPE4_SCR_LEN 0x01E0
163 #define TYPE4_LCR_LEN 0x03A0
164
165 #define TYPE4_SME_FMT 0x00
166 #define TYPE4_LME_FMT 0x10
167 #define TYPE4_SCR_FMT 0x40
168 #define TYPE4_LCR_FMT 0x50
169
170 struct type4_sme {
171         struct type4_hdr header;
172         unsigned char    message[128];
173         unsigned char    exponent[128];
174         unsigned char    modulus[128];
175 };
176
177 struct type4_lme {
178         struct type4_hdr header;
179         unsigned char    message[256];
180         unsigned char    exponent[256];
181         unsigned char    modulus[256];
182 };
183
184 struct type4_scr {
185         struct type4_hdr header;
186         unsigned char    message[128];
187         unsigned char    dp[72];
188         unsigned char    dq[64];
189         unsigned char    p[72];
190         unsigned char    q[64];
191         unsigned char    u[72];
192 };
193
194 struct type4_lcr {
195         struct type4_hdr header;
196         unsigned char    message[256];
197         unsigned char    dp[136];
198         unsigned char    dq[128];
199         unsigned char    p[136];
200         unsigned char    q[128];
201         unsigned char    u[136];
202 };
203
204 union type4_msg {
205         struct type4_sme sme;
206         struct type4_lme lme;
207         struct type4_scr scr;
208         struct type4_lcr lcr;
209 };
210
211 struct type84_hdr {
212         unsigned char  reserved1;
213         unsigned char  code;
214         unsigned short len;
215         unsigned char  reserved2[4];
216 };
217
218 #define TYPE84_RSP_CODE 0x84
219
220 struct type6_hdr {
221         unsigned char reserved1;
222         unsigned char type;
223         unsigned char reserved2[2];
224         unsigned char right[4];
225         unsigned char reserved3[2];
226         unsigned char reserved4[2];
227         unsigned char apfs[4];
228         unsigned int  offset1;
229         unsigned int  offset2;
230         unsigned int  offset3;
231         unsigned int  offset4;
232         unsigned char agent_id[16];
233         unsigned char rqid[2];
234         unsigned char reserved5[2];
235         unsigned char function_code[2];
236         unsigned char reserved6[2];
237         unsigned int  ToCardLen1;
238         unsigned int  ToCardLen2;
239         unsigned int  ToCardLen3;
240         unsigned int  ToCardLen4;
241         unsigned int  FromCardLen1;
242         unsigned int  FromCardLen2;
243         unsigned int  FromCardLen3;
244         unsigned int  FromCardLen4;
245 };
246
247 struct CPRB {
248         unsigned char cprb_len[2];
249         unsigned char cprb_ver_id;
250         unsigned char pad_000;
251         unsigned char srpi_rtcode[4];
252         unsigned char srpi_verb;
253         unsigned char flags;
254         unsigned char func_id[2];
255         unsigned char checkpoint_flag;
256         unsigned char resv2;
257         unsigned char req_parml[2];
258         unsigned char req_parmp[4];
259         unsigned char req_datal[4];
260         unsigned char req_datap[4];
261         unsigned char rpl_parml[2];
262         unsigned char pad_001[2];
263         unsigned char rpl_parmp[4];
264         unsigned char rpl_datal[4];
265         unsigned char rpl_datap[4];
266         unsigned char ccp_rscode[2];
267         unsigned char ccp_rtcode[2];
268         unsigned char repd_parml[2];
269         unsigned char mac_data_len[2];
270         unsigned char repd_datal[4];
271         unsigned char req_pc[2];
272         unsigned char res_origin[8];
273         unsigned char mac_value[8];
274         unsigned char logon_id[8];
275         unsigned char usage_domain[2];
276         unsigned char resv3[18];
277         unsigned char svr_namel[2];
278         unsigned char svr_name[8];
279 };
280
281 struct type6_msg {
282         struct type6_hdr header;
283         struct CPRB      CPRB;
284 };
285
286 struct type86_hdr {
287         unsigned char reserved1;
288         unsigned char type;
289         unsigned char format;
290         unsigned char reserved2;
291         unsigned char reply_code;
292         unsigned char reserved3[3];
293 };
294
295 #define TYPE86_RSP_CODE 0x86
296 #define TYPE86_FMT2     0x02
297
298 struct type86_fmt2_msg {
299         struct type86_hdr header;
300         unsigned char     reserved[4];
301         unsigned char     apfs[4];
302         unsigned int      count1;
303         unsigned int      offset1;
304         unsigned int      count2;
305         unsigned int      offset2;
306         unsigned int      count3;
307         unsigned int      offset3;
308         unsigned int      count4;
309         unsigned int      offset4;
310 };
311
312 static struct type6_hdr static_type6_hdr = {
313         0x00,
314         0x06,
315         {0x00,0x00},
316         {0x00,0x00,0x00,0x00},
317         {0x00,0x00},
318         {0x00,0x00},
319         {0x00,0x00,0x00,0x00},
320         0x00000058,
321         0x00000000,
322         0x00000000,
323         0x00000000,
324         {0x01,0x00,0x43,0x43,0x41,0x2D,0x41,0x50,
325          0x50,0x4C,0x20,0x20,0x20,0x01,0x01,0x01},
326         {0x00,0x00},
327         {0x00,0x00},
328         {0x50,0x44},
329         {0x00,0x00},
330         0x00000000,
331         0x00000000,
332         0x00000000,
333         0x00000000,
334         0x00000000,
335         0x00000000,
336         0x00000000,
337         0x00000000
338 };
339
340 static struct type6_hdr static_type6_hdrX = {
341         0x00,
342         0x06,
343         {0x00,0x00},
344         {0x00,0x00,0x00,0x00},
345         {0x00,0x00},
346         {0x00,0x00},
347         {0x00,0x00,0x00,0x00},
348         0x00000058,
349         0x00000000,
350         0x00000000,
351         0x00000000,
352         {0x43,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
353          0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
354         {0x00,0x00},
355         {0x00,0x00},
356         {0x50,0x44},
357         {0x00,0x00},
358         0x00000000,
359         0x00000000,
360         0x00000000,
361         0x00000000,
362         0x00000000,
363         0x00000000,
364         0x00000000,
365         0x00000000
366 };
367
368 static struct CPRB static_cprb = {
369         {0x70,0x00},
370         0x41,
371         0x00,
372         {0x00,0x00,0x00,0x00},
373         0x00,
374         0x00,
375         {0x54,0x32},
376         0x01,
377         0x00,
378         {0x00,0x00},
379         {0x00,0x00,0x00,0x00},
380         {0x00,0x00,0x00,0x00},
381         {0x00,0x00,0x00,0x00},
382         {0x00,0x00},
383         {0x00,0x00},
384         {0x00,0x00,0x00,0x00},
385         {0x00,0x00,0x00,0x00},
386         {0x00,0x00,0x00,0x00},
387         {0x00,0x00},
388         {0x00,0x00},
389         {0x00,0x00},
390         {0x00,0x00},
391         {0x00,0x00,0x00,0x00},
392         {0x00,0x00},
393         {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
394         {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
395         {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
396         {0x00,0x00},
397         {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
398          0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
399          0x00,0x00},
400         {0x08,0x00},
401         {0x49,0x43,0x53,0x46,0x20,0x20,0x20,0x20}
402 };
403
404 struct function_and_rules_block {
405         unsigned char function_code[2];
406         unsigned char ulen[2];
407         unsigned char only_rule[8];
408 };
409
410 static struct function_and_rules_block static_pkd_function_and_rules = {
411         {0x50,0x44},
412         {0x0A,0x00},
413         {'P','K','C','S','-','1','.','2'}
414 };
415
416 static struct function_and_rules_block static_pke_function_and_rules = {
417         {0x50,0x4B},
418         {0x0A,0x00},
419         {'P','K','C','S','-','1','.','2'}
420 };
421
422 struct T6_keyBlock_hdr {
423         unsigned char blen[2];
424         unsigned char ulen[2];
425         unsigned char flags[2];
426 };
427
428 static struct T6_keyBlock_hdr static_T6_keyBlock_hdr = {
429         {0x89,0x01},
430         {0x87,0x01},
431         {0x00}
432 };
433
434 static struct CPRBX static_cprbx = {
435         0x00DC,
436         0x02,
437         {0x00,0x00,0x00},
438         {0x54,0x32},
439         {0x00,0x00,0x00,0x00},
440         0x00000000,
441         0x00000000,
442         0x00000000,
443         0x00000000,
444         0x00000000,
445         0x00000000,
446         0x00000000,
447         {0x00,0x00,0x00,0x00},
448         0x00000000,
449         {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
450          0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
451         {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
452          0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
453         {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
454          0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
455         {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
456          0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
457         {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
458          0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
459         {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
460          0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
461         0x0000,
462         0x0000,
463         0x00000000,
464         {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
465         {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
466         0x00,
467         0x00,
468         0x0000,
469         {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
470         {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
471          0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
472          0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
473 };
474
475 static struct function_and_rules_block static_pkd_function_and_rulesX_MCL2 = {
476         {0x50,0x44},
477         {0x00,0x0A},
478         {'P','K','C','S','-','1','.','2'}
479 };
480
481 static struct function_and_rules_block static_pke_function_and_rulesX_MCL2 = {
482         {0x50,0x4B},
483         {0x00,0x0A},
484         {'Z','E','R','O','-','P','A','D'}
485 };
486
487 static struct function_and_rules_block static_pkd_function_and_rulesX = {
488         {0x50,0x44},
489         {0x00,0x0A},
490         {'Z','E','R','O','-','P','A','D'}
491 };
492
493 static struct function_and_rules_block static_pke_function_and_rulesX = {
494         {0x50,0x4B},
495         {0x00,0x0A},
496         {'M','R','P',' ',' ',' ',' ',' '}
497 };
498
499 static unsigned char static_PKE_function_code[2] = {0x50, 0x4B};
500
501 struct T6_keyBlock_hdrX {
502         unsigned short blen;
503         unsigned short ulen;
504         unsigned char flags[2];
505 };
506
507 static unsigned char static_pad[256] = {
508 0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD,0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57,
509 0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B,0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39,
510 0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5,0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D,
511 0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB,0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F,
512 0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9,0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45,
513 0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9,0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F,
514 0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD,0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D,
515 0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD,0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9,
516 0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B,0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B,
517 0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B,0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD,
518 0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7,0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1,
519 0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3,0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23,
520 0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55,0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43,
521 0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F,0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F,
522 0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5,0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD,
523 0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41,0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09
524 };
525
526 static struct cca_private_ext_ME static_pvt_me_key = {
527         {
528                 0x1E,
529                 0x00,
530                 0x0183,
531                 {0x00,0x00,0x00,0x00}
532         },
533
534         {
535                 0x02,
536                 0x00,
537                 0x016C,
538                 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
539                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
540                  0x00,0x00,0x00,0x00},
541                 {0x00,0x00,0x00,0x00},
542                 0x00,
543                 0x00,
544                 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
545                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
546                  0x00,0x00,0x00,0x00},
547                 {0x80,0x00,0x00,0x00},
548                 {0x00,0x00,0x00,0x00,0x00,0x00},
549                 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
550                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
551                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
552                 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
553                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
554                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
555                 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
556                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
557                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
558                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
559                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
560                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
561                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
562                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
563                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
564                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
565                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
566                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
567                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
568                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
569                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
570                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
571                 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
572                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
573                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
574                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
575                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
576                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
577                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
578                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
579                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
580                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
581                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
582                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
583                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
584                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
585                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
586                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
587         },
588
589         {
590                 0x04,
591                 0x00,
592                 0x000F,
593                 {0x00,0x00},
594                 0x0003,
595                 0x0000,
596                 0x0000,
597                 {0x01,0x00,0x01}
598         }
599 };
600
601 static struct cca_public_key static_public_key = {
602         {
603                 0x1E,
604                 0x00,
605                 0x0000,
606                 {0x00,0x00,0x00,0x00}
607         },
608
609         {
610                 0x04,
611                 0x00,
612                 0x0000,
613                 {0x00,0x00},
614                 0x0000,
615                 0x0000,
616                 0x0000,
617                 {0x01,0x00,0x01}
618         }
619 };
620
621 #define FIXED_TYPE6_ME_LEN 0x0000025F
622
623 #define FIXED_TYPE6_ME_EN_LEN 0x000000F0
624
625 #define FIXED_TYPE6_ME_LENX 0x000002CB
626
627 #define FIXED_TYPE6_ME_EN_LENX 0x0000015C
628
629 static struct cca_public_sec static_cca_pub_sec = {
630         0x04,
631         0x00,
632         0x000f,
633         {0x00,0x00},
634         0x0003,
635         0x0000,
636         0x0000,
637         {0x01,0x00,0x01}
638 };
639
640 #define FIXED_TYPE6_CR_LEN 0x00000177
641
642 #define FIXED_TYPE6_CR_LENX 0x000001E3
643
644 #define MAX_RESPONSE_SIZE 0x00000710
645
646 #define MAX_RESPONSEX_SIZE 0x0000077C
647
648 #define RESPONSE_CPRB_SIZE  0x000006B8
649 #define RESPONSE_CPRBX_SIZE 0x00000724
650
651 struct error_hdr {
652         unsigned char reserved1;
653         unsigned char type;
654         unsigned char reserved2[2];
655         unsigned char reply_code;
656         unsigned char reserved3[3];
657 };
658
659 #define TYPE82_RSP_CODE 0x82
660
661 #define REP82_ERROR_MACHINE_FAILURE  0x10
662 #define REP82_ERROR_PREEMPT_FAILURE  0x12
663 #define REP82_ERROR_CHECKPT_FAILURE  0x14
664 #define REP82_ERROR_MESSAGE_TYPE     0x20
665 #define REP82_ERROR_INVALID_COMM_CD  0x21
666 #define REP82_ERROR_INVALID_MSG_LEN  0x23
667 #define REP82_ERROR_RESERVD_FIELD    0x24
668 #define REP82_ERROR_FORMAT_FIELD     0x29
669 #define REP82_ERROR_INVALID_COMMAND  0x30
670 #define REP82_ERROR_MALFORMED_MSG    0x40
671 #define REP82_ERROR_RESERVED_FIELDO  0x50
672 #define REP82_ERROR_WORD_ALIGNMENT   0x60
673 #define REP82_ERROR_MESSAGE_LENGTH   0x80
674 #define REP82_ERROR_OPERAND_INVALID  0x82
675 #define REP82_ERROR_OPERAND_SIZE     0x84
676 #define REP82_ERROR_EVEN_MOD_IN_OPND 0x85
677 #define REP82_ERROR_RESERVED_FIELD   0x88
678 #define REP82_ERROR_TRANSPORT_FAIL   0x90
679 #define REP82_ERROR_PACKET_TRUNCATED 0xA0
680 #define REP82_ERROR_ZERO_BUFFER_LEN  0xB0
681
682 #define CALLER_HEADER 12
683
684 static inline int
685 testq(int q_nr, int *q_depth, int *dev_type, struct ap_status_word *stat)
686 {
687         int ccode;
688
689         asm volatile
690 #ifdef __s390x__
691         ("      llgfr   0,%4            \n"
692          "      slgr    1,1             \n"
693          "      lgr     2,1             \n"
694          "0:    .long   0xb2af0000      \n"
695          "1:    ipm     %0              \n"
696          "      srl     %0,28           \n"
697          "      iihh    %0,0            \n"
698          "      iihl    %0,0            \n"
699          "      lgr     %1,1            \n"
700          "      lgr     %3,2            \n"
701          "      srl     %3,24           \n"
702          "      sll     2,24            \n"
703          "      srl     2,24            \n"
704          "      lgr     %2,2            \n"
705          "2:                            \n"
706          ".section .fixup,\"ax\"        \n"
707          "3:                            \n"
708          "      lhi     %0,%h5          \n"
709          "      jg      2b              \n"
710          ".previous                     \n"
711          ".section __ex_table,\"a\"     \n"
712          "      .align  8               \n"
713          "      .quad   0b,3b           \n"
714          "      .quad   1b,3b           \n"
715          ".previous"
716          :"=d" (ccode),"=d" (*stat),"=d" (*q_depth), "=d" (*dev_type)
717          :"d" (q_nr), "K" (DEV_TSQ_EXCEPTION)
718          :"cc","0","1","2","memory");
719 #else
720         ("      lr      0,%4            \n"
721          "      slr     1,1             \n"
722          "      lr      2,1             \n"
723          "0:    .long   0xb2af0000      \n"
724          "1:    ipm     %0              \n"
725          "      srl     %0,28           \n"
726          "      lr      %1,1            \n"
727          "      lr      %3,2            \n"
728          "      srl     %3,24           \n"
729          "      sll     2,24            \n"
730          "      srl     2,24            \n"
731          "      lr      %2,2            \n"
732          "2:                            \n"
733          ".section .fixup,\"ax\"        \n"
734          "3:                            \n"
735          "      lhi     %0,%h5          \n"
736          "      bras    1,4f            \n"
737          "      .long   2b              \n"
738          "4:                            \n"
739          "      l       1,0(1)          \n"
740          "      br      1               \n"
741          ".previous                     \n"
742          ".section __ex_table,\"a\"     \n"
743          "      .align  4               \n"
744          "      .long   0b,3b           \n"
745          "      .long   1b,3b           \n"
746          ".previous"
747          :"=d" (ccode),"=d" (*stat),"=d" (*q_depth), "=d" (*dev_type)
748          :"d" (q_nr), "K" (DEV_TSQ_EXCEPTION)
749          :"cc","0","1","2","memory");
750 #endif
751         return ccode;
752 }
753
754 static inline int
755 resetq(int q_nr, struct ap_status_word *stat_p)
756 {
757         int ccode;
758
759         asm volatile
760 #ifdef __s390x__
761         ("      llgfr   0,%2            \n"
762          "      lghi    1,1             \n"
763          "      sll     1,24            \n"
764          "      or      0,1             \n"
765          "      slgr    1,1             \n"
766          "      lgr     2,1             \n"
767          "0:    .long   0xb2af0000      \n"
768          "1:    ipm     %0              \n"
769          "      srl     %0,28           \n"
770          "      iihh    %0,0            \n"
771          "      iihl    %0,0            \n"
772          "      lgr     %1,1            \n"
773          "2:                            \n"
774          ".section .fixup,\"ax\"        \n"
775          "3:                            \n"
776          "      lhi     %0,%h3          \n"
777          "      jg      2b              \n"
778          ".previous                     \n"
779          ".section __ex_table,\"a\"     \n"
780          "      .align  8               \n"
781          "      .quad   0b,3b           \n"
782          "      .quad   1b,3b           \n"
783          ".previous"
784          :"=d" (ccode),"=d" (*stat_p)
785          :"d" (q_nr), "K" (DEV_RSQ_EXCEPTION)
786          :"cc","0","1","2","memory");
787 #else
788         ("      lr      0,%2            \n"
789          "      lhi     1,1             \n"
790          "      sll     1,24            \n"
791          "      or      0,1             \n"
792          "      slr     1,1             \n"
793          "      lr      2,1             \n"
794          "0:    .long   0xb2af0000      \n"
795          "1:    ipm     %0              \n"
796          "      srl     %0,28           \n"
797          "      lr      %1,1            \n"
798          "2:                            \n"
799          ".section .fixup,\"ax\"        \n"
800          "3:                            \n"
801          "      lhi     %0,%h3          \n"
802          "      bras    1,4f            \n"
803          "      .long   2b              \n"
804          "4:                            \n"
805          "      l       1,0(1)          \n"
806          "      br      1               \n"
807          ".previous                     \n"
808          ".section __ex_table,\"a\"     \n"
809          "      .align  4               \n"
810          "      .long   0b,3b           \n"
811          "      .long   1b,3b           \n"
812          ".previous"
813          :"=d" (ccode),"=d" (*stat_p)
814          :"d" (q_nr), "K" (DEV_RSQ_EXCEPTION)
815          :"cc","0","1","2","memory");
816 #endif
817         return ccode;
818 }
819
820 static inline int
821 sen(int msg_len, unsigned char *msg_ext, struct ap_status_word *stat)
822 {
823         int ccode;
824
825         asm volatile
826 #ifdef __s390x__
827         ("      lgr     6,%3            \n"
828          "      llgfr   7,%2            \n"
829          "      llgt    0,0(6)          \n"
830          "      lghi    1,64            \n"
831          "      sll     1,24            \n"
832          "      or      0,1             \n"
833          "      la      6,4(6)          \n"
834          "      llgt    2,0(6)          \n"
835          "      llgt    3,4(6)          \n"
836          "      la      6,8(6)          \n"
837          "      slr     1,1             \n"
838          "0:    .long   0xb2ad0026      \n"
839          "1:    brc     2,0b            \n"
840          "      ipm     %0              \n"
841          "      srl     %0,28           \n"
842          "      iihh    %0,0            \n"
843          "      iihl    %0,0            \n"
844          "      lgr     %1,1            \n"
845          "2:                            \n"
846          ".section .fixup,\"ax\"        \n"
847          "3:                            \n"
848          "      lhi     %0,%h4          \n"
849          "      jg      2b              \n"
850          ".previous                     \n"
851          ".section __ex_table,\"a\"     \n"
852          "      .align  8               \n"
853          "      .quad   0b,3b           \n"
854          "      .quad   1b,3b           \n"
855          ".previous"
856          :"=d" (ccode),"=d" (*stat)
857          :"d" (msg_len),"a" (msg_ext), "K" (DEV_SEN_EXCEPTION)
858          :"cc","0","1","2","3","6","7","memory");
859 #else
860         ("      lr      6,%3            \n"
861          "      lr      7,%2            \n"
862          "      l       0,0(6)          \n"
863          "      lhi     1,64            \n"
864          "      sll     1,24            \n"
865          "      or      0,1             \n"
866          "      la      6,4(6)          \n"
867          "      l       2,0(6)          \n"
868          "      l       3,4(6)          \n"
869          "      la      6,8(6)          \n"
870          "      slr     1,1             \n"
871          "0:    .long   0xb2ad0026      \n"
872          "1:    brc     2,0b            \n"
873          "      ipm     %0              \n"
874          "      srl     %0,28           \n"
875          "      lr      %1,1            \n"
876          "2:                            \n"
877          ".section .fixup,\"ax\"        \n"
878          "3:                            \n"
879          "      lhi     %0,%h4          \n"
880          "      bras    1,4f            \n"
881          "      .long   2b              \n"
882          "4:                            \n"
883          "      l       1,0(1)          \n"
884          "      br      1               \n"
885          ".previous                     \n"
886          ".section __ex_table,\"a\"     \n"
887          "      .align  4               \n"
888          "      .long   0b,3b           \n"
889          "      .long   1b,3b           \n"
890          ".previous"
891          :"=d" (ccode),"=d" (*stat)
892          :"d" (msg_len),"a" (msg_ext), "K" (DEV_SEN_EXCEPTION)
893          :"cc","0","1","2","3","6","7","memory");
894 #endif
895         return ccode;
896 }
897
898 static inline int
899 rec(int q_nr, int buff_l, unsigned char *rsp, unsigned char *id,
900     struct ap_status_word *st)
901 {
902         int ccode;
903
904         asm volatile
905 #ifdef __s390x__
906         ("      llgfr   0,%2            \n"
907          "      lgr     3,%4            \n"
908          "      lgr     6,%3            \n"
909          "      llgfr   7,%5            \n"
910          "      lghi    1,128           \n"
911          "      sll     1,24            \n"
912          "      or      0,1             \n"
913          "      slgr    1,1             \n"
914          "      lgr     2,1             \n"
915          "      lgr     4,1             \n"
916          "      lgr     5,1             \n"
917          "0:    .long   0xb2ae0046      \n"
918          "1:    brc     2,0b            \n"
919          "      brc     4,0b            \n"
920          "      ipm     %0              \n"
921          "      srl     %0,28           \n"
922          "      iihh    %0,0            \n"
923          "      iihl    %0,0            \n"
924          "      lgr     %1,1            \n"
925          "      st      4,0(3)          \n"
926          "      st      5,4(3)          \n"
927          "2:                            \n"
928          ".section .fixup,\"ax\"        \n"
929          "3:                            \n"
930          "      lhi   %0,%h6            \n"
931          "      jg    2b                \n"
932          ".previous                     \n"
933          ".section __ex_table,\"a\"     \n"
934          "   .align     8               \n"
935          "   .quad      0b,3b           \n"
936          "   .quad      1b,3b           \n"
937          ".previous"
938          :"=d"(ccode),"=d"(*st)
939          :"d" (q_nr), "d" (rsp), "d" (id), "d" (buff_l), "K" (DEV_REC_EXCEPTION)
940          :"cc","0","1","2","3","4","5","6","7","memory");
941 #else
942         ("      lr      0,%2            \n"
943          "      lr      3,%4            \n"
944          "      lr      6,%3            \n"
945          "      lr      7,%5            \n"
946          "      lhi     1,128           \n"
947          "      sll     1,24            \n"
948          "      or      0,1             \n"
949          "      slr     1,1             \n"
950          "      lr      2,1             \n"
951          "      lr      4,1             \n"
952          "      lr      5,1             \n"
953          "0:    .long   0xb2ae0046      \n"
954          "1:    brc     2,0b            \n"
955          "      brc     4,0b            \n"
956          "      ipm     %0              \n"
957          "      srl     %0,28           \n"
958          "      lr      %1,1            \n"
959          "      st      4,0(3)          \n"
960          "      st      5,4(3)          \n"
961          "2:                            \n"
962          ".section .fixup,\"ax\"        \n"
963          "3:                            \n"
964          "      lhi   %0,%h6            \n"
965          "      bras  1,4f              \n"
966          "      .long 2b                \n"
967          "4:                            \n"
968          "      l     1,0(1)            \n"
969          "      br    1                 \n"
970          ".previous                     \n"
971          ".section __ex_table,\"a\"     \n"
972          "   .align     4               \n"
973          "   .long      0b,3b           \n"
974          "   .long      1b,3b           \n"
975          ".previous"
976          :"=d"(ccode),"=d"(*st)
977          :"d" (q_nr), "d" (rsp), "d" (id), "d" (buff_l), "K" (DEV_REC_EXCEPTION)
978          :"cc","0","1","2","3","4","5","6","7","memory");
979 #endif
980         return ccode;
981 }
982
983 static inline void
984 itoLe2(int *i_p, unsigned char *lechars)
985 {
986         *lechars       = *((unsigned char *) i_p + sizeof(int) - 1);
987         *(lechars + 1) = *((unsigned char *) i_p + sizeof(int) - 2);
988 }
989
990 static inline void
991 le2toI(unsigned char *lechars, int *i_p)
992 {
993         unsigned char *ic_p;
994         *i_p = 0;
995         ic_p = (unsigned char *) i_p;
996         *(ic_p + 2) = *(lechars + 1);
997         *(ic_p + 3) = *(lechars);
998 }
999
1000 static inline int
1001 is_empty(unsigned char *ptr, int len)
1002 {
1003         return !memcmp(ptr, (unsigned char *) &static_pvt_me_key+60, len);
1004 }
1005
1006 enum hdstat
1007 query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type)
1008 {
1009         int q_nr, i, t_depth, t_dev_type;
1010         enum devstat ccode;
1011         struct ap_status_word stat_word;
1012         enum hdstat stat;
1013         int break_out;
1014
1015         q_nr = (deviceNr << SKIP_BITL) + cdx;
1016         stat = HD_BUSY;
1017         ccode = testq(q_nr, &t_depth, &t_dev_type, &stat_word);
1018         PDEBUG("ccode %d response_code %02X\n", ccode, stat_word.response_code);
1019         break_out = 0;
1020         for (i = 0; i < resetNr; i++) {
1021                 if (ccode > 3) {
1022                         PRINTKC("Exception testing device %d\n", i);
1023                         return HD_TSQ_EXCEPTION;
1024                 }
1025                 switch (ccode) {
1026                 case 0:
1027                         PDEBUG("t_dev_type %d\n", t_dev_type);
1028                         break_out = 1;
1029                         stat = HD_ONLINE;
1030                         *q_depth = t_depth + 1;
1031                         switch (t_dev_type) {
1032                         case OTHER_HW:
1033                                 stat = HD_NOT_THERE;
1034                                 *dev_type = NILDEV;
1035                                 break;
1036                         case PCICA_HW:
1037                                 *dev_type = PCICA;
1038                                 break;
1039                         case PCICC_HW:
1040                                 *dev_type = PCICC;
1041                                 break;
1042                         case PCIXCC_HW:
1043                                 *dev_type = PCIXCC_UNK;
1044                                 break;
1045                         case CEX2C_HW:
1046                                 *dev_type = CEX2C;
1047                                 break;
1048                         default:
1049                                 *dev_type = NILDEV;
1050                                 break;
1051                         }
1052                         PDEBUG("available device %d: Q depth = %d, dev "
1053                                "type = %d, stat = %02X%02X%02X%02X\n",
1054                                deviceNr, *q_depth, *dev_type,
1055                                stat_word.q_stat_flags,
1056                                stat_word.response_code,
1057                                stat_word.reserved[0],
1058                                stat_word.reserved[1]);
1059                         break;
1060                 case 3:
1061                         switch (stat_word.response_code) {
1062                         case AP_RESPONSE_NORMAL:
1063                                 stat = HD_ONLINE;
1064                                 break_out = 1;
1065                                 *q_depth = t_depth + 1;
1066                                 *dev_type = t_dev_type;
1067                                 PDEBUG("cc3, available device "
1068                                        "%d: Q depth = %d, dev "
1069                                        "type = %d, stat = "
1070                                        "%02X%02X%02X%02X\n",
1071                                        deviceNr, *q_depth,
1072                                        *dev_type,
1073                                        stat_word.q_stat_flags,
1074                                        stat_word.response_code,
1075                                        stat_word.reserved[0],
1076                                        stat_word.reserved[1]);
1077                                 break;
1078                         case AP_RESPONSE_Q_NOT_AVAIL:
1079                                 stat = HD_NOT_THERE;
1080                                 break_out = 1;
1081                                 break;
1082                         case AP_RESPONSE_RESET_IN_PROGRESS:
1083                                 PDEBUG("device %d in reset\n",
1084                                        deviceNr);
1085                                 break;
1086                         case AP_RESPONSE_DECONFIGURED:
1087                                 stat = HD_DECONFIGURED;
1088                                 break_out = 1;
1089                                 break;
1090                         case AP_RESPONSE_CHECKSTOPPED:
1091                                 stat = HD_CHECKSTOPPED;
1092                                 break_out = 1;
1093                                 break;
1094                         case AP_RESPONSE_BUSY:
1095                                 PDEBUG("device %d busy\n",
1096                                        deviceNr);
1097                                 break;
1098                         default:
1099                                 break;
1100                         }
1101                         break;
1102                 default:
1103                         stat = HD_NOT_THERE;
1104                         break_out = 1;
1105                         break;
1106                 }
1107                 if (break_out)
1108                         break;
1109
1110                 udelay(5);
1111
1112                 ccode = testq(q_nr, &t_depth, &t_dev_type, &stat_word);
1113         }
1114         return stat;
1115 }
1116
1117 enum devstat
1118 reset_device(int deviceNr, int cdx, int resetNr)
1119 {
1120         int q_nr, ccode = 0, dummy_qdepth, dummy_devType, i;
1121         struct ap_status_word stat_word;
1122         enum devstat stat;
1123         int break_out;
1124
1125         q_nr = (deviceNr << SKIP_BITL) + cdx;
1126         stat = DEV_GONE;
1127         ccode = resetq(q_nr, &stat_word);
1128         if (ccode > 3)
1129                 return DEV_RSQ_EXCEPTION;
1130
1131         break_out = 0;
1132         for (i = 0; i < resetNr; i++) {
1133                 switch (ccode) {
1134                 case 0:
1135                         stat = DEV_ONLINE;
1136                         if (stat_word.q_stat_flags & AP_Q_STATUS_EMPTY)
1137                                 break_out = 1;
1138                         break;
1139                 case 3:
1140                         switch (stat_word.response_code) {
1141                         case AP_RESPONSE_NORMAL:
1142                                 stat = DEV_ONLINE;
1143                                 if (stat_word.q_stat_flags & AP_Q_STATUS_EMPTY)
1144                                         break_out = 1;
1145                                 break;
1146                         case AP_RESPONSE_Q_NOT_AVAIL:
1147                         case AP_RESPONSE_DECONFIGURED:
1148                         case AP_RESPONSE_CHECKSTOPPED:
1149                                 stat = DEV_GONE;
1150                                 break_out = 1;
1151                                 break;
1152                         case AP_RESPONSE_RESET_IN_PROGRESS:
1153                         case AP_RESPONSE_BUSY:
1154                         default:
1155                                 break;
1156                         }
1157                         break;
1158                 default:
1159                         stat = DEV_GONE;
1160                         break_out = 1;
1161                         break;
1162                 }
1163                 if (break_out == 1)
1164                         break;
1165                 udelay(5);
1166
1167                 ccode = testq(q_nr, &dummy_qdepth, &dummy_devType, &stat_word);
1168                 if (ccode > 3) {
1169                         stat = DEV_TSQ_EXCEPTION;
1170                         break;
1171                 }
1172         }
1173         PDEBUG("Number of testq's needed for reset: %d\n", i);
1174
1175         if (i >= resetNr) {
1176           stat = DEV_GONE;
1177         }
1178
1179         return stat;
1180 }
1181
1182 #ifdef DEBUG_HYDRA_MSGS
1183 static inline void
1184 print_buffer(unsigned char *buffer, int bufflen)
1185 {
1186         int i;
1187         for (i = 0; i < bufflen; i += 16) {
1188                 PRINTK("%04X: %02X%02X%02X%02X %02X%02X%02X%02X "
1189                        "%02X%02X%02X%02X %02X%02X%02X%02X\n", i,
1190                        buffer[i+0], buffer[i+1], buffer[i+2], buffer[i+3],
1191                        buffer[i+4], buffer[i+5], buffer[i+6], buffer[i+7],
1192                        buffer[i+8], buffer[i+9], buffer[i+10], buffer[i+11],
1193                        buffer[i+12], buffer[i+13], buffer[i+14], buffer[i+15]);
1194         }
1195 }
1196 #endif
1197
1198 enum devstat
1199 send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext)
1200 {
1201         struct ap_status_word stat_word;
1202         enum devstat stat;
1203         int ccode;
1204         u32 *q_nr_p = (u32 *)msg_ext;
1205
1206         *q_nr_p = (dev_nr << SKIP_BITL) + cdx;
1207         PDEBUG("msg_len passed to sen: %d\n", msg_len);
1208         PDEBUG("q number passed to sen: %02x%02x%02x%02x\n",
1209                msg_ext[0], msg_ext[1], msg_ext[2], msg_ext[3]);
1210         stat = DEV_GONE;
1211
1212 #ifdef DEBUG_HYDRA_MSGS
1213         PRINTK("Request header: %02X%02X%02X%02X %02X%02X%02X%02X "
1214                "%02X%02X%02X%02X\n",
1215                msg_ext[0], msg_ext[1], msg_ext[2], msg_ext[3],
1216                msg_ext[4], msg_ext[5], msg_ext[6], msg_ext[7],
1217                msg_ext[8], msg_ext[9], msg_ext[10], msg_ext[11]);
1218         print_buffer(msg_ext+CALLER_HEADER, msg_len);
1219 #endif
1220
1221         ccode = sen(msg_len, msg_ext, &stat_word);
1222         if (ccode > 3)
1223                 return DEV_SEN_EXCEPTION;
1224
1225         PDEBUG("nq cc: %u, st: %02x%02x%02x%02x\n",
1226                ccode, stat_word.q_stat_flags, stat_word.response_code,
1227                stat_word.reserved[0], stat_word.reserved[1]);
1228         switch (ccode) {
1229         case 0:
1230                 stat = DEV_ONLINE;
1231                 break;
1232         case 1:
1233                 stat = DEV_GONE;
1234                 break;
1235         case 3:
1236                 switch (stat_word.response_code) {
1237                 case AP_RESPONSE_NORMAL:
1238                         stat = DEV_ONLINE;
1239                         break;
1240                 case AP_RESPONSE_Q_FULL:
1241                         stat = DEV_QUEUE_FULL;
1242                         break;
1243                 default:
1244                         stat = DEV_GONE;
1245                         break;
1246                 }
1247                 break;
1248         default:
1249                 stat = DEV_GONE;
1250                 break;
1251         }
1252
1253         return stat;
1254 }
1255
1256 enum devstat
1257 receive_from_AP(int dev_nr, int cdx, int resplen, unsigned char *resp,
1258                 unsigned char *psmid)
1259 {
1260         int ccode;
1261         struct ap_status_word stat_word;
1262         enum devstat stat;
1263
1264         memset(resp, 0x00, 8);
1265
1266         ccode = rec((dev_nr << SKIP_BITL) + cdx, resplen, resp, psmid,
1267                     &stat_word);
1268         if (ccode > 3)
1269                 return DEV_REC_EXCEPTION;
1270
1271         PDEBUG("dq cc: %u, st: %02x%02x%02x%02x\n",
1272                ccode, stat_word.q_stat_flags, stat_word.response_code,
1273                stat_word.reserved[0], stat_word.reserved[1]);
1274
1275         stat = DEV_GONE;
1276         switch (ccode) {
1277         case 0:
1278                 stat = DEV_ONLINE;
1279 #ifdef DEBUG_HYDRA_MSGS
1280                 print_buffer(resp, resplen);
1281 #endif
1282                 break;
1283         case 3:
1284                 switch (stat_word.response_code) {
1285                 case AP_RESPONSE_NORMAL:
1286                         stat = DEV_ONLINE;
1287                         break;
1288                 case AP_RESPONSE_NO_PENDING_REPLY:
1289                         if (stat_word.q_stat_flags & AP_Q_STATUS_EMPTY)
1290                                 stat = DEV_EMPTY;
1291                         else
1292                                 stat = DEV_NO_WORK;
1293                         break;
1294                 case AP_RESPONSE_INDEX_TOO_BIG:
1295                 case AP_RESPONSE_NO_FIRST_PART:
1296                 case AP_RESPONSE_MESSAGE_TOO_BIG:
1297                         stat = DEV_BAD_MESSAGE;
1298                         break;
1299                 default:
1300                         break;
1301                 }
1302                 break;
1303         default:
1304                 break;
1305         }
1306
1307         return stat;
1308 }
1309
1310 static inline int
1311 pad_msg(unsigned char *buffer, int  totalLength, int msgLength)
1312 {
1313         int pad_len;
1314
1315         for (pad_len = 0; pad_len < (totalLength - msgLength); pad_len++)
1316                 if (buffer[pad_len] != 0x00)
1317                         break;
1318         pad_len -= 3;
1319         if (pad_len < 8)
1320                 return SEN_PAD_ERROR;
1321
1322         buffer[0] = 0x00;
1323         buffer[1] = 0x02;
1324
1325         memcpy(buffer+2, static_pad, pad_len);
1326
1327         buffer[pad_len + 2] = 0x00;
1328
1329         return 0;
1330 }
1331
1332 static inline int
1333 is_common_public_key(unsigned char *key, int len)
1334 {
1335         int i;
1336
1337         for (i = 0; i < len; i++)
1338                 if (key[i])
1339                         break;
1340         key += i;
1341         len -= i;
1342         if (((len == 1) && (key[0] == 3)) ||
1343             ((len == 3) && (key[0] == 1) && (key[1] == 0) && (key[2] == 1)))
1344                 return 1;
1345
1346         return 0;
1347 }
1348
1349 static int
1350 ICAMEX_msg_to_type4MEX_msg(struct ica_rsa_modexpo *icaMex_p, int *z90cMsg_l_p,
1351                            union type4_msg *z90cMsg_p)
1352 {
1353         int mod_len, msg_size, mod_tgt_len, exp_tgt_len, inp_tgt_len;
1354         unsigned char *mod_tgt, *exp_tgt, *inp_tgt;
1355         union type4_msg *tmp_type4_msg;
1356
1357         mod_len = icaMex_p->inputdatalength;
1358
1359         msg_size = ((mod_len <= 128) ? TYPE4_SME_LEN : TYPE4_LME_LEN) +
1360                     CALLER_HEADER;
1361
1362         memset(z90cMsg_p, 0, msg_size);
1363
1364         tmp_type4_msg = (union type4_msg *)
1365                 ((unsigned char *) z90cMsg_p + CALLER_HEADER);
1366
1367         tmp_type4_msg->sme.header.msg_type_code = TYPE4_TYPE_CODE;
1368         tmp_type4_msg->sme.header.request_code = TYPE4_REQU_CODE;
1369
1370         if (mod_len <= 128) {
1371                 tmp_type4_msg->sme.header.msg_fmt = TYPE4_SME_FMT;
1372                 tmp_type4_msg->sme.header.msg_len = TYPE4_SME_LEN;
1373                 mod_tgt = tmp_type4_msg->sme.modulus;
1374                 mod_tgt_len = sizeof(tmp_type4_msg->sme.modulus);
1375                 exp_tgt = tmp_type4_msg->sme.exponent;
1376                 exp_tgt_len = sizeof(tmp_type4_msg->sme.exponent);
1377                 inp_tgt = tmp_type4_msg->sme.message;
1378                 inp_tgt_len = sizeof(tmp_type4_msg->sme.message);
1379         } else {
1380                 tmp_type4_msg->lme.header.msg_fmt = TYPE4_LME_FMT;
1381                 tmp_type4_msg->lme.header.msg_len = TYPE4_LME_LEN;
1382                 mod_tgt = tmp_type4_msg->lme.modulus;
1383                 mod_tgt_len = sizeof(tmp_type4_msg->lme.modulus);
1384                 exp_tgt = tmp_type4_msg->lme.exponent;
1385                 exp_tgt_len = sizeof(tmp_type4_msg->lme.exponent);
1386                 inp_tgt = tmp_type4_msg->lme.message;
1387                 inp_tgt_len = sizeof(tmp_type4_msg->lme.message);
1388         }
1389
1390         mod_tgt += (mod_tgt_len - mod_len);
1391         if (copy_from_user(mod_tgt, icaMex_p->n_modulus, mod_len))
1392                 return SEN_RELEASED;
1393         if (is_empty(mod_tgt, mod_len))
1394                 return SEN_USER_ERROR;
1395         exp_tgt += (exp_tgt_len - mod_len);
1396         if (copy_from_user(exp_tgt, icaMex_p->b_key, mod_len))
1397                 return SEN_RELEASED;
1398         if (is_empty(exp_tgt, mod_len))
1399                 return SEN_USER_ERROR;
1400         inp_tgt += (inp_tgt_len - mod_len);
1401         if (copy_from_user(inp_tgt, icaMex_p->inputdata, mod_len))
1402                 return SEN_RELEASED;
1403         if (is_empty(inp_tgt, mod_len))
1404                 return SEN_USER_ERROR;
1405
1406         *z90cMsg_l_p = msg_size - CALLER_HEADER;
1407
1408         return 0;
1409 }
1410
1411 static int
1412 ICACRT_msg_to_type4CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p,
1413                            int *z90cMsg_l_p, union type4_msg *z90cMsg_p)
1414 {
1415         int mod_len, short_len, long_len, tmp_size, p_tgt_len, q_tgt_len,
1416             dp_tgt_len, dq_tgt_len, u_tgt_len, inp_tgt_len;
1417         unsigned char *p_tgt, *q_tgt, *dp_tgt, *dq_tgt, *u_tgt, *inp_tgt;
1418         union type4_msg *tmp_type4_msg;
1419
1420         mod_len = icaMsg_p->inputdatalength;
1421         short_len = mod_len / 2;
1422         long_len = mod_len / 2 + 8;
1423
1424         tmp_size = ((mod_len <= 128) ? TYPE4_SCR_LEN : TYPE4_LCR_LEN) +
1425                     CALLER_HEADER;
1426
1427         memset(z90cMsg_p, 0, tmp_size);
1428
1429         tmp_type4_msg = (union type4_msg *)
1430                 ((unsigned char *) z90cMsg_p + CALLER_HEADER);
1431
1432         tmp_type4_msg->scr.header.msg_type_code = TYPE4_TYPE_CODE;
1433         tmp_type4_msg->scr.header.request_code = TYPE4_REQU_CODE;
1434         if (mod_len <= 128) {
1435                 tmp_type4_msg->scr.header.msg_fmt = TYPE4_SCR_FMT;
1436                 tmp_type4_msg->scr.header.msg_len = TYPE4_SCR_LEN;
1437                 p_tgt = tmp_type4_msg->scr.p;
1438                 p_tgt_len = sizeof(tmp_type4_msg->scr.p);
1439                 q_tgt = tmp_type4_msg->scr.q;
1440                 q_tgt_len = sizeof(tmp_type4_msg->scr.q);
1441                 dp_tgt = tmp_type4_msg->scr.dp;
1442                 dp_tgt_len = sizeof(tmp_type4_msg->scr.dp);
1443                 dq_tgt = tmp_type4_msg->scr.dq;
1444                 dq_tgt_len = sizeof(tmp_type4_msg->scr.dq);
1445                 u_tgt = tmp_type4_msg->scr.u;
1446                 u_tgt_len = sizeof(tmp_type4_msg->scr.u);
1447                 inp_tgt = tmp_type4_msg->scr.message;
1448                 inp_tgt_len = sizeof(tmp_type4_msg->scr.message);
1449         } else {
1450                 tmp_type4_msg->lcr.header.msg_fmt = TYPE4_LCR_FMT;
1451                 tmp_type4_msg->lcr.header.msg_len = TYPE4_LCR_LEN;
1452                 p_tgt = tmp_type4_msg->lcr.p;
1453                 p_tgt_len = sizeof(tmp_type4_msg->lcr.p);
1454                 q_tgt = tmp_type4_msg->lcr.q;
1455                 q_tgt_len = sizeof(tmp_type4_msg->lcr.q);
1456                 dp_tgt = tmp_type4_msg->lcr.dp;
1457                 dp_tgt_len = sizeof(tmp_type4_msg->lcr.dp);
1458                 dq_tgt = tmp_type4_msg->lcr.dq;
1459                 dq_tgt_len = sizeof(tmp_type4_msg->lcr.dq);
1460                 u_tgt = tmp_type4_msg->lcr.u;
1461                 u_tgt_len = sizeof(tmp_type4_msg->lcr.u);
1462                 inp_tgt = tmp_type4_msg->lcr.message;
1463                 inp_tgt_len = sizeof(tmp_type4_msg->lcr.message);
1464         }
1465
1466         p_tgt += (p_tgt_len - long_len);
1467         if (copy_from_user(p_tgt, icaMsg_p->np_prime, long_len))
1468                 return SEN_RELEASED;
1469         if (is_empty(p_tgt, long_len))
1470                 return SEN_USER_ERROR;
1471         q_tgt += (q_tgt_len - short_len);
1472         if (copy_from_user(q_tgt, icaMsg_p->nq_prime, short_len))
1473                 return SEN_RELEASED;
1474         if (is_empty(q_tgt, short_len))
1475                 return SEN_USER_ERROR;
1476         dp_tgt += (dp_tgt_len - long_len);
1477         if (copy_from_user(dp_tgt, icaMsg_p->bp_key, long_len))
1478                 return SEN_RELEASED;
1479         if (is_empty(dp_tgt, long_len))
1480                 return SEN_USER_ERROR;
1481         dq_tgt += (dq_tgt_len - short_len);
1482         if (copy_from_user(dq_tgt, icaMsg_p->bq_key, short_len))
1483                 return SEN_RELEASED;
1484         if (is_empty(dq_tgt, short_len))
1485                 return SEN_USER_ERROR;
1486         u_tgt += (u_tgt_len - long_len);
1487         if (copy_from_user(u_tgt, icaMsg_p->u_mult_inv, long_len))
1488                 return SEN_RELEASED;
1489         if (is_empty(u_tgt, long_len))
1490                 return SEN_USER_ERROR;
1491         inp_tgt += (inp_tgt_len - mod_len);
1492         if (copy_from_user(inp_tgt, icaMsg_p->inputdata, mod_len))
1493                 return SEN_RELEASED;
1494         if (is_empty(inp_tgt, mod_len))
1495                 return SEN_USER_ERROR;
1496
1497         *z90cMsg_l_p = tmp_size - CALLER_HEADER;
1498
1499         return 0;
1500 }
1501
1502 static int
1503 ICAMEX_msg_to_type6MEX_de_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx,
1504                               int *z90cMsg_l_p, struct type6_msg *z90cMsg_p)
1505 {
1506         int mod_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l;
1507         unsigned char *temp;
1508         struct type6_hdr *tp6Hdr_p;
1509         struct CPRB *cprb_p;
1510         struct cca_private_ext_ME *key_p;
1511         static int deprecated_msg_count = 0;
1512
1513         mod_len = icaMsg_p->inputdatalength;
1514         tmp_size = FIXED_TYPE6_ME_LEN + mod_len;
1515         total_CPRB_len = tmp_size - sizeof(struct type6_hdr);
1516         parmBlock_l = total_CPRB_len - sizeof(struct CPRB);
1517         tmp_size = 4*((tmp_size + 3)/4) + CALLER_HEADER;
1518
1519         memset(z90cMsg_p, 0, tmp_size);
1520
1521         temp = (unsigned char *)z90cMsg_p + CALLER_HEADER;
1522         memcpy(temp, &static_type6_hdr, sizeof(struct type6_hdr));
1523         tp6Hdr_p = (struct type6_hdr *)temp;
1524         tp6Hdr_p->ToCardLen1 = 4*((total_CPRB_len+3)/4);
1525         tp6Hdr_p->FromCardLen1 = RESPONSE_CPRB_SIZE;
1526
1527         temp += sizeof(struct type6_hdr);
1528         memcpy(temp, &static_cprb, sizeof(struct CPRB));
1529         cprb_p = (struct CPRB *) temp;
1530         cprb_p->usage_domain[0]= (unsigned char)cdx;
1531         itoLe2(&parmBlock_l, cprb_p->req_parml);
1532         itoLe2((int *)&(tp6Hdr_p->FromCardLen1), cprb_p->rpl_parml);
1533
1534         temp += sizeof(struct CPRB);
1535         memcpy(temp, &static_pkd_function_and_rules,
1536                sizeof(struct function_and_rules_block));
1537
1538         temp += sizeof(struct function_and_rules_block);
1539         vud_len = 2 + icaMsg_p->inputdatalength;
1540         itoLe2(&vud_len, temp);
1541
1542         temp += 2;
1543         if (copy_from_user(temp, icaMsg_p->inputdata, mod_len))
1544                 return SEN_RELEASED;
1545         if (is_empty(temp, mod_len))
1546                 return SEN_USER_ERROR;
1547
1548         temp += mod_len;
1549         memcpy(temp, &static_T6_keyBlock_hdr, sizeof(struct T6_keyBlock_hdr));
1550
1551         temp += sizeof(struct T6_keyBlock_hdr);
1552         memcpy(temp, &static_pvt_me_key, sizeof(struct cca_private_ext_ME));
1553         key_p = (struct cca_private_ext_ME *)temp;
1554         temp = key_p->pvtMESec.exponent + sizeof(key_p->pvtMESec.exponent)
1555                - mod_len;
1556         if (copy_from_user(temp, icaMsg_p->b_key, mod_len))
1557                 return SEN_RELEASED;
1558         if (is_empty(temp, mod_len))
1559                 return SEN_USER_ERROR;
1560
1561         if (is_common_public_key(temp, mod_len)) {
1562                 if (deprecated_msg_count < 20) {
1563                         PRINTK("Common public key used for modex decrypt\n");
1564                         deprecated_msg_count++;
1565                         if (deprecated_msg_count == 20)
1566                                 PRINTK("No longer issuing messages about common"
1567                                        " public key for modex decrypt.\n");
1568                 }
1569                 return SEN_NOT_AVAIL;
1570         }
1571
1572         temp = key_p->pvtMESec.modulus + sizeof(key_p->pvtMESec.modulus)
1573                - mod_len;
1574         if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len))
1575                 return SEN_RELEASED;
1576         if (is_empty(temp, mod_len))
1577                 return SEN_USER_ERROR;
1578
1579         key_p->pubMESec.modulus_bit_len = 8 * mod_len;
1580
1581         *z90cMsg_l_p = tmp_size - CALLER_HEADER;
1582
1583         return 0;
1584 }
1585
1586 static int
1587 ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx,
1588                               int *z90cMsg_l_p, struct type6_msg *z90cMsg_p)
1589 {
1590         int mod_len, vud_len, exp_len, key_len;
1591         int pad_len, tmp_size, total_CPRB_len, parmBlock_l, i;
1592         unsigned char *temp_exp, *exp_p, *temp;
1593         struct type6_hdr *tp6Hdr_p;
1594         struct CPRB *cprb_p;
1595         struct cca_public_key *key_p;
1596         struct T6_keyBlock_hdr *keyb_p;
1597
1598         temp_exp = kmalloc(256, GFP_KERNEL);
1599         if (!temp_exp)
1600                 return EGETBUFF;
1601         mod_len = icaMsg_p->inputdatalength;
1602         if (copy_from_user(temp_exp, icaMsg_p->b_key, mod_len)) {
1603                 kfree(temp_exp);
1604                 return SEN_RELEASED;
1605         }
1606         if (is_empty(temp_exp, mod_len)) {
1607                 kfree(temp_exp);
1608                 return SEN_USER_ERROR;
1609         }
1610
1611         exp_p = temp_exp;
1612         for (i = 0; i < mod_len; i++)
1613                 if (exp_p[i])
1614                         break;
1615         if (i >= mod_len) {
1616                 kfree(temp_exp);
1617                 return SEN_USER_ERROR;
1618         }
1619
1620         exp_len = mod_len - i;
1621         exp_p += i;
1622
1623         PDEBUG("exp_len after computation: %08x\n", exp_len);
1624         tmp_size = FIXED_TYPE6_ME_EN_LEN + 2 * mod_len + exp_len;
1625         total_CPRB_len = tmp_size - sizeof(struct type6_hdr);
1626         parmBlock_l = total_CPRB_len - sizeof(struct CPRB);
1627         tmp_size = 4*((tmp_size + 3)/4) + CALLER_HEADER;
1628
1629         vud_len = 2 + mod_len;
1630         memset(z90cMsg_p, 0, tmp_size);
1631
1632         temp = (unsigned char *)z90cMsg_p + CALLER_HEADER;
1633         memcpy(temp, &static_type6_hdr, sizeof(struct type6_hdr));
1634         tp6Hdr_p = (struct type6_hdr *)temp;
1635         tp6Hdr_p->ToCardLen1 = 4*((total_CPRB_len+3)/4);
1636         tp6Hdr_p->FromCardLen1 = RESPONSE_CPRB_SIZE;
1637         memcpy(tp6Hdr_p->function_code, static_PKE_function_code,
1638                sizeof(static_PKE_function_code));
1639         temp += sizeof(struct type6_hdr);
1640         memcpy(temp, &static_cprb, sizeof(struct CPRB));
1641         cprb_p = (struct CPRB *) temp;
1642         cprb_p->usage_domain[0]= (unsigned char)cdx;
1643         itoLe2((int *)&(tp6Hdr_p->FromCardLen1), cprb_p->rpl_parml);
1644         temp += sizeof(struct CPRB);
1645         memcpy(temp, &static_pke_function_and_rules,
1646                  sizeof(struct function_and_rules_block));
1647         temp += sizeof(struct function_and_rules_block);
1648         temp += 2;
1649         if (copy_from_user(temp, icaMsg_p->inputdata, mod_len)) {
1650                 kfree(temp_exp);
1651                 return SEN_RELEASED;
1652         }
1653         if (is_empty(temp, mod_len)) {
1654                 kfree(temp_exp);
1655                 return SEN_USER_ERROR;
1656         }
1657         if ((temp[0] != 0x00) || (temp[1] != 0x02)) {
1658                 kfree(temp_exp);
1659                 return SEN_NOT_AVAIL;
1660         }
1661         for (i = 2; i < mod_len; i++)
1662                 if (temp[i] == 0x00)
1663                         break;
1664         if ((i < 9) || (i > (mod_len - 2))) {
1665                 kfree(temp_exp);
1666                 return SEN_NOT_AVAIL;
1667         }
1668         pad_len = i + 1;
1669         vud_len = mod_len - pad_len;
1670         memmove(temp, temp+pad_len, vud_len);
1671         temp -= 2;
1672         vud_len += 2;
1673         itoLe2(&vud_len, temp);
1674         temp += (vud_len);
1675         keyb_p = (struct T6_keyBlock_hdr *)temp;
1676         temp += sizeof(struct T6_keyBlock_hdr);
1677         memcpy(temp, &static_public_key, sizeof(static_public_key));
1678         key_p = (struct cca_public_key *)temp;
1679         temp = key_p->pubSec.exponent;
1680         memcpy(temp, exp_p, exp_len);
1681         kfree(temp_exp);
1682         temp += exp_len;
1683         if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len))
1684                 return SEN_RELEASED;
1685         if (is_empty(temp, mod_len))
1686                 return SEN_USER_ERROR;
1687         key_p->pubSec.modulus_bit_len = 8 * mod_len;
1688         key_p->pubSec.modulus_byte_len = mod_len;
1689         key_p->pubSec.exponent_len = exp_len;
1690         key_p->pubSec.section_length = CALLER_HEADER + mod_len + exp_len;
1691         key_len = key_p->pubSec.section_length + sizeof(struct cca_token_hdr);
1692         key_p->pubHdr.token_length = key_len;
1693         key_len += 4;
1694         itoLe2(&key_len, keyb_p->ulen);
1695         key_len += 2;
1696         itoLe2(&key_len, keyb_p->blen);
1697         parmBlock_l -= pad_len;
1698         itoLe2(&parmBlock_l, cprb_p->req_parml);
1699         *z90cMsg_l_p = tmp_size - CALLER_HEADER;
1700
1701         return 0;
1702 }
1703
1704 static int
1705 ICACRT_msg_to_type6CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx,
1706                            int *z90cMsg_l_p, struct type6_msg *z90cMsg_p)
1707 {
1708         int mod_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l, short_len;
1709         int long_len, pad_len, keyPartsLen, tmp_l;
1710         unsigned char *tgt_p, *temp;
1711         struct type6_hdr *tp6Hdr_p;
1712         struct CPRB *cprb_p;
1713         struct cca_token_hdr *keyHdr_p;
1714         struct cca_pvt_ext_CRT_sec *pvtSec_p;
1715         struct cca_public_sec *pubSec_p;
1716
1717         mod_len = icaMsg_p->inputdatalength;
1718         short_len = mod_len / 2;
1719         long_len = 8 + short_len;
1720         keyPartsLen = 3 * long_len + 2 * short_len;
1721         pad_len = (8 - (keyPartsLen % 8)) % 8;
1722         keyPartsLen += pad_len + mod_len;
1723         tmp_size = FIXED_TYPE6_CR_LEN + keyPartsLen + mod_len;
1724         total_CPRB_len = tmp_size -  sizeof(struct type6_hdr);
1725         parmBlock_l = total_CPRB_len - sizeof(struct CPRB);
1726         vud_len = 2 + mod_len;
1727         tmp_size = 4*((tmp_size + 3)/4) + CALLER_HEADER;
1728
1729         memset(z90cMsg_p, 0, tmp_size);
1730         tgt_p = (unsigned char *)z90cMsg_p + CALLER_HEADER;
1731         memcpy(tgt_p, &static_type6_hdr, sizeof(struct type6_hdr));
1732         tp6Hdr_p = (struct type6_hdr *)tgt_p;
1733         tp6Hdr_p->ToCardLen1 = 4*((total_CPRB_len+3)/4);
1734         tp6Hdr_p->FromCardLen1 = RESPONSE_CPRB_SIZE;
1735         tgt_p += sizeof(struct type6_hdr);
1736         cprb_p = (struct CPRB *) tgt_p;
1737         memcpy(tgt_p, &static_cprb, sizeof(struct CPRB));
1738         cprb_p->usage_domain[0]= *((unsigned char *)(&(cdx))+3);
1739         itoLe2(&parmBlock_l, cprb_p->req_parml);
1740         memcpy(cprb_p->rpl_parml, cprb_p->req_parml,
1741                sizeof(cprb_p->req_parml));
1742         tgt_p += sizeof(struct CPRB);
1743         memcpy(tgt_p, &static_pkd_function_and_rules,
1744                sizeof(struct function_and_rules_block));
1745         tgt_p += sizeof(struct function_and_rules_block);
1746         itoLe2(&vud_len, tgt_p);
1747         tgt_p += 2;
1748         if (copy_from_user(tgt_p, icaMsg_p->inputdata, mod_len))
1749                 return SEN_RELEASED;
1750         if (is_empty(tgt_p, mod_len))
1751                 return SEN_USER_ERROR;
1752         tgt_p += mod_len;
1753         tmp_l = sizeof(struct T6_keyBlock_hdr) + sizeof(struct cca_token_hdr) +
1754                 sizeof(struct cca_pvt_ext_CRT_sec) + 0x0F + keyPartsLen;
1755         itoLe2(&tmp_l, tgt_p);
1756         temp = tgt_p + 2;
1757         tmp_l -= 2;
1758         itoLe2(&tmp_l, temp);
1759         tgt_p += sizeof(struct T6_keyBlock_hdr);
1760         keyHdr_p = (struct cca_token_hdr *)tgt_p;
1761         keyHdr_p->token_identifier = CCA_TKN_HDR_ID_EXT;
1762         tmp_l -= 4;
1763         keyHdr_p->token_length = tmp_l;
1764         tgt_p += sizeof(struct cca_token_hdr);
1765         pvtSec_p = (struct cca_pvt_ext_CRT_sec *)tgt_p;
1766         pvtSec_p->section_identifier = CCA_PVT_EXT_CRT_SEC_ID_PVT;
1767         pvtSec_p->section_length =
1768                 sizeof(struct cca_pvt_ext_CRT_sec) + keyPartsLen;
1769         pvtSec_p->key_format = CCA_PVT_EXT_CRT_SEC_FMT_CL;
1770         pvtSec_p->key_use_flags[0] = CCA_PVT_USAGE_ALL;
1771         pvtSec_p->p_len = long_len;
1772         pvtSec_p->q_len = short_len;
1773         pvtSec_p->dp_len = long_len;
1774         pvtSec_p->dq_len = short_len;
1775         pvtSec_p->u_len = long_len;
1776         pvtSec_p->mod_len = mod_len;
1777         pvtSec_p->pad_len = pad_len;
1778         tgt_p += sizeof(struct cca_pvt_ext_CRT_sec);
1779         if (copy_from_user(tgt_p, icaMsg_p->np_prime, long_len))
1780                 return SEN_RELEASED;
1781         if (is_empty(tgt_p, long_len))
1782                 return SEN_USER_ERROR;
1783         tgt_p += long_len;
1784         if (copy_from_user(tgt_p, icaMsg_p->nq_prime, short_len))
1785                 return SEN_RELEASED;
1786         if (is_empty(tgt_p, short_len))
1787                 return SEN_USER_ERROR;
1788         tgt_p += short_len;
1789         if (copy_from_user(tgt_p, icaMsg_p->bp_key, long_len))
1790                 return SEN_RELEASED;
1791         if (is_empty(tgt_p, long_len))
1792                 return SEN_USER_ERROR;
1793         tgt_p += long_len;
1794         if (copy_from_user(tgt_p, icaMsg_p->bq_key, short_len))
1795                 return SEN_RELEASED;
1796         if (is_empty(tgt_p, short_len))
1797                 return SEN_USER_ERROR;
1798         tgt_p += short_len;
1799         if (copy_from_user(tgt_p, icaMsg_p->u_mult_inv, long_len))
1800                 return SEN_RELEASED;
1801         if (is_empty(tgt_p, long_len))
1802                 return SEN_USER_ERROR;
1803         tgt_p += long_len;
1804         tgt_p += pad_len;
1805         memset(tgt_p, 0xFF, mod_len);
1806         tgt_p += mod_len;
1807         memcpy(tgt_p, &static_cca_pub_sec, sizeof(struct cca_public_sec));
1808         pubSec_p = (struct cca_public_sec *) tgt_p;
1809         pubSec_p->modulus_bit_len = 8 * mod_len;
1810         *z90cMsg_l_p = tmp_size - CALLER_HEADER;
1811
1812         return 0;
1813 }
1814
1815 static int
1816 ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx,
1817                             int *z90cMsg_l_p, struct type6_msg *z90cMsg_p,
1818                             int dev_type)
1819 {
1820         int mod_len, exp_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l;
1821         int key_len, i;
1822         unsigned char *temp_exp, *tgt_p, *temp, *exp_p;
1823         struct type6_hdr *tp6Hdr_p;
1824         struct CPRBX *cprbx_p;
1825         struct cca_public_key *key_p;
1826         struct T6_keyBlock_hdrX *keyb_p;
1827
1828         temp_exp = kmalloc(256, GFP_KERNEL);
1829         if (!temp_exp)
1830                 return EGETBUFF;
1831         mod_len = icaMsg_p->inputdatalength;
1832         if (copy_from_user(temp_exp, icaMsg_p->b_key, mod_len)) {
1833                 kfree(temp_exp);
1834                 return SEN_RELEASED;
1835         }
1836         if (is_empty(temp_exp, mod_len)) {
1837                 kfree(temp_exp);
1838                 return SEN_USER_ERROR;
1839         }
1840         exp_p = temp_exp;
1841         for (i = 0; i < mod_len; i++)
1842                 if (exp_p[i])
1843                         break;
1844         if (i >= mod_len) {
1845                 kfree(temp_exp);
1846                 return SEN_USER_ERROR;
1847         }
1848         exp_len = mod_len - i;
1849         exp_p += i;
1850         PDEBUG("exp_len after computation: %08x\n", exp_len);
1851         tmp_size = FIXED_TYPE6_ME_EN_LENX + 2 * mod_len + exp_len;
1852         total_CPRB_len = tmp_size - sizeof(struct type6_hdr);
1853         parmBlock_l = total_CPRB_len - sizeof(struct CPRBX);
1854         tmp_size = tmp_size + CALLER_HEADER;
1855         vud_len = 2 + mod_len;
1856         memset(z90cMsg_p, 0, tmp_size);
1857         tgt_p = (unsigned char *)z90cMsg_p + CALLER_HEADER;
1858         memcpy(tgt_p, &static_type6_hdrX, sizeof(struct type6_hdr));
1859         tp6Hdr_p = (struct type6_hdr *)tgt_p;
1860         tp6Hdr_p->ToCardLen1 = total_CPRB_len;
1861         tp6Hdr_p->FromCardLen1 = RESPONSE_CPRBX_SIZE;
1862         memcpy(tp6Hdr_p->function_code, static_PKE_function_code,
1863                sizeof(static_PKE_function_code));
1864         tgt_p += sizeof(struct type6_hdr);
1865         memcpy(tgt_p, &static_cprbx, sizeof(struct CPRBX));
1866         cprbx_p = (struct CPRBX *) tgt_p;
1867         cprbx_p->domain = (unsigned short)cdx;
1868         cprbx_p->rpl_msgbl = RESPONSE_CPRBX_SIZE;
1869         tgt_p += sizeof(struct CPRBX);
1870         if (dev_type == PCIXCC_MCL2)
1871                 memcpy(tgt_p, &static_pke_function_and_rulesX_MCL2,
1872                        sizeof(struct function_and_rules_block));
1873         else
1874                 memcpy(tgt_p, &static_pke_function_and_rulesX,
1875                        sizeof(struct function_and_rules_block));
1876         tgt_p += sizeof(struct function_and_rules_block);
1877
1878         tgt_p += 2;
1879         if (copy_from_user(tgt_p, icaMsg_p->inputdata, mod_len)) {
1880                 kfree(temp_exp);
1881                 return SEN_RELEASED;
1882         }
1883         if (is_empty(tgt_p, mod_len)) {
1884                 kfree(temp_exp);
1885                 return SEN_USER_ERROR;
1886         }
1887         tgt_p -= 2;
1888         *((short *)tgt_p) = (short) vud_len;
1889         tgt_p += vud_len;
1890         keyb_p = (struct T6_keyBlock_hdrX *)tgt_p;
1891         tgt_p += sizeof(struct T6_keyBlock_hdrX);
1892         memcpy(tgt_p, &static_public_key, sizeof(static_public_key));
1893         key_p = (struct cca_public_key *)tgt_p;
1894         temp = key_p->pubSec.exponent;
1895         memcpy(temp, exp_p, exp_len);
1896         kfree(temp_exp);
1897         temp += exp_len;
1898         if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len))
1899                 return SEN_RELEASED;
1900         if (is_empty(temp, mod_len))
1901                 return SEN_USER_ERROR;
1902         key_p->pubSec.modulus_bit_len = 8 * mod_len;
1903         key_p->pubSec.modulus_byte_len = mod_len;
1904         key_p->pubSec.exponent_len = exp_len;
1905         key_p->pubSec.section_length = CALLER_HEADER + mod_len + exp_len;
1906         key_len = key_p->pubSec.section_length + sizeof(struct cca_token_hdr);
1907         key_p->pubHdr.token_length = key_len;
1908         key_len += 4;
1909         keyb_p->ulen = (unsigned short)key_len;
1910         key_len += 2;
1911         keyb_p->blen = (unsigned short)key_len;
1912         cprbx_p->req_parml = parmBlock_l;
1913         *z90cMsg_l_p = tmp_size - CALLER_HEADER;
1914
1915         return 0;
1916 }
1917
1918 static int
1919 ICACRT_msg_to_type6CRT_msgX(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx,
1920                             int *z90cMsg_l_p, struct type6_msg *z90cMsg_p,
1921                             int dev_type)
1922 {
1923         int mod_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l, short_len;
1924         int long_len, pad_len, keyPartsLen, tmp_l;
1925         unsigned char *tgt_p, *temp;
1926         struct type6_hdr *tp6Hdr_p;
1927         struct CPRBX *cprbx_p;
1928         struct cca_token_hdr *keyHdr_p;
1929         struct cca_pvt_ext_CRT_sec *pvtSec_p;
1930         struct cca_public_sec *pubSec_p;
1931
1932         mod_len = icaMsg_p->inputdatalength;
1933         short_len = mod_len / 2;
1934         long_len = 8 + short_len;
1935         keyPartsLen = 3 * long_len + 2 * short_len;
1936         pad_len = (8 - (keyPartsLen % 8)) % 8;
1937         keyPartsLen += pad_len + mod_len;
1938         tmp_size = FIXED_TYPE6_CR_LENX + keyPartsLen + mod_len;
1939         total_CPRB_len = tmp_size -  sizeof(struct type6_hdr);
1940         parmBlock_l = total_CPRB_len - sizeof(struct CPRBX);
1941         vud_len = 2 + mod_len;
1942         tmp_size = tmp_size + CALLER_HEADER;
1943         memset(z90cMsg_p, 0, tmp_size);
1944         tgt_p = (unsigned char *)z90cMsg_p + CALLER_HEADER;
1945         memcpy(tgt_p, &static_type6_hdrX, sizeof(struct type6_hdr));
1946         tp6Hdr_p = (struct type6_hdr *)tgt_p;
1947         tp6Hdr_p->ToCardLen1 = total_CPRB_len;
1948         tp6Hdr_p->FromCardLen1 = RESPONSE_CPRBX_SIZE;
1949         tgt_p += sizeof(struct type6_hdr);
1950         cprbx_p = (struct CPRBX *) tgt_p;
1951         memcpy(tgt_p, &static_cprbx, sizeof(struct CPRBX));
1952         cprbx_p->domain = (unsigned short)cdx;
1953         cprbx_p->req_parml = parmBlock_l;
1954         cprbx_p->rpl_msgbl = parmBlock_l;
1955         tgt_p += sizeof(struct CPRBX);
1956         if (dev_type == PCIXCC_MCL2)
1957                 memcpy(tgt_p, &static_pkd_function_and_rulesX_MCL2,
1958                        sizeof(struct function_and_rules_block));
1959         else
1960                 memcpy(tgt_p, &static_pkd_function_and_rulesX,
1961                        sizeof(struct function_and_rules_block));
1962         tgt_p += sizeof(struct function_and_rules_block);
1963         *((short *)tgt_p) = (short) vud_len;
1964         tgt_p += 2;
1965         if (copy_from_user(tgt_p, icaMsg_p->inputdata, mod_len))
1966                 return SEN_RELEASED;
1967         if (is_empty(tgt_p, mod_len))
1968                 return SEN_USER_ERROR;
1969         tgt_p += mod_len;
1970         tmp_l = sizeof(struct T6_keyBlock_hdr) + sizeof(struct cca_token_hdr) +
1971                 sizeof(struct cca_pvt_ext_CRT_sec) + 0x0F + keyPartsLen;
1972         *((short *)tgt_p) = (short) tmp_l;
1973         temp = tgt_p + 2;
1974         tmp_l -= 2;
1975         *((short *)temp) = (short) tmp_l;
1976         tgt_p += sizeof(struct T6_keyBlock_hdr);
1977         keyHdr_p = (struct cca_token_hdr *)tgt_p;
1978         keyHdr_p->token_identifier = CCA_TKN_HDR_ID_EXT;
1979         tmp_l -= 4;
1980         keyHdr_p->token_length = tmp_l;
1981         tgt_p += sizeof(struct cca_token_hdr);
1982         pvtSec_p = (struct cca_pvt_ext_CRT_sec *)tgt_p;
1983         pvtSec_p->section_identifier = CCA_PVT_EXT_CRT_SEC_ID_PVT;
1984         pvtSec_p->section_length =
1985                 sizeof(struct cca_pvt_ext_CRT_sec) + keyPartsLen;
1986         pvtSec_p->key_format = CCA_PVT_EXT_CRT_SEC_FMT_CL;
1987         pvtSec_p->key_use_flags[0] = CCA_PVT_USAGE_ALL;
1988         pvtSec_p->p_len = long_len;
1989         pvtSec_p->q_len = short_len;
1990         pvtSec_p->dp_len = long_len;
1991         pvtSec_p->dq_len = short_len;
1992         pvtSec_p->u_len = long_len;
1993         pvtSec_p->mod_len = mod_len;
1994         pvtSec_p->pad_len = pad_len;
1995         tgt_p += sizeof(struct cca_pvt_ext_CRT_sec);
1996         if (copy_from_user(tgt_p, icaMsg_p->np_prime, long_len))
1997                 return SEN_RELEASED;
1998         if (is_empty(tgt_p, long_len))
1999                 return SEN_USER_ERROR;
2000         tgt_p += long_len;
2001         if (copy_from_user(tgt_p, icaMsg_p->nq_prime, short_len))
2002                 return SEN_RELEASED;
2003         if (is_empty(tgt_p, short_len))
2004                 return SEN_USER_ERROR;
2005         tgt_p += short_len;
2006         if (copy_from_user(tgt_p, icaMsg_p->bp_key, long_len))
2007                 return SEN_RELEASED;
2008         if (is_empty(tgt_p, long_len))
2009                 return SEN_USER_ERROR;
2010         tgt_p += long_len;
2011         if (copy_from_user(tgt_p, icaMsg_p->bq_key, short_len))
2012                 return SEN_RELEASED;
2013         if (is_empty(tgt_p, short_len))
2014                 return SEN_USER_ERROR;
2015         tgt_p += short_len;
2016         if (copy_from_user(tgt_p, icaMsg_p->u_mult_inv, long_len))
2017                 return SEN_RELEASED;
2018         if (is_empty(tgt_p, long_len))
2019                 return SEN_USER_ERROR;
2020         tgt_p += long_len;
2021         tgt_p += pad_len;
2022         memset(tgt_p, 0xFF, mod_len);
2023         tgt_p += mod_len;
2024         memcpy(tgt_p, &static_cca_pub_sec, sizeof(struct cca_public_sec));
2025         pubSec_p = (struct cca_public_sec *) tgt_p;
2026         pubSec_p->modulus_bit_len = 8 * mod_len;
2027         *z90cMsg_l_p = tmp_size - CALLER_HEADER;
2028
2029         return 0;
2030 }
2031
2032 int
2033 convert_request(unsigned char *buffer, int func, unsigned short function,
2034                 int cdx, int dev_type, int *msg_l_p, unsigned char *msg_p)
2035 {
2036         if (dev_type == PCICA) {
2037                 if (func == ICARSACRT)
2038                         return ICACRT_msg_to_type4CRT_msg(
2039                                 (struct ica_rsa_modexpo_crt *) buffer,
2040                                 msg_l_p, (union type4_msg *) msg_p);
2041                 else
2042                         return ICAMEX_msg_to_type4MEX_msg(
2043                                 (struct ica_rsa_modexpo *) buffer,
2044                                 msg_l_p, (union type4_msg *) msg_p);
2045         }
2046         if (dev_type == PCICC) {
2047                 if (func == ICARSACRT)
2048                         return ICACRT_msg_to_type6CRT_msg(
2049                                 (struct ica_rsa_modexpo_crt *) buffer,
2050                                 cdx, msg_l_p, (struct type6_msg *)msg_p);
2051                 if (function == PCI_FUNC_KEY_ENCRYPT)
2052                         return ICAMEX_msg_to_type6MEX_en_msg(
2053                                 (struct ica_rsa_modexpo *) buffer,
2054                                 cdx, msg_l_p, (struct type6_msg *) msg_p);
2055                 else
2056                         return ICAMEX_msg_to_type6MEX_de_msg(
2057                                 (struct ica_rsa_modexpo *) buffer,
2058                                 cdx, msg_l_p, (struct type6_msg *) msg_p);
2059         }
2060         if ((dev_type == PCIXCC_MCL2) ||
2061             (dev_type == PCIXCC_MCL3) ||
2062             (dev_type == CEX2C)) {
2063                 if (func == ICARSACRT)
2064                         return ICACRT_msg_to_type6CRT_msgX(
2065                                 (struct ica_rsa_modexpo_crt *) buffer,
2066                                 cdx, msg_l_p, (struct type6_msg *) msg_p,
2067                                 dev_type);
2068                 else
2069                         return ICAMEX_msg_to_type6MEX_msgX(
2070                                 (struct ica_rsa_modexpo *) buffer,
2071                                 cdx, msg_l_p, (struct type6_msg *) msg_p,
2072                                 dev_type);
2073         }
2074
2075         return 0;
2076 }
2077
2078 int ext_bitlens_msg_count = 0;
2079 static inline void
2080 unset_ext_bitlens(void)
2081 {
2082         if (!ext_bitlens_msg_count) {
2083                 PRINTK("Unable to use coprocessors for extended bitlengths. "
2084                        "Using PCICAs (if present) for extended bitlengths. "
2085                        "This is not an error.\n");
2086                 ext_bitlens_msg_count++;
2087         }
2088         ext_bitlens = 0;
2089 }
2090
2091 int
2092 convert_response(unsigned char *response, unsigned char *buffer,
2093                  int *respbufflen_p, unsigned char *resp_buff)
2094 {
2095         struct ica_rsa_modexpo *icaMsg_p = (struct ica_rsa_modexpo *) buffer;
2096         struct error_hdr *errh_p = (struct error_hdr *) response;
2097         struct type84_hdr *t84h_p = (struct type84_hdr *) response;
2098         struct type86_fmt2_msg *t86m_p =  (struct type86_fmt2_msg *) response;
2099         int reply_code, service_rc, service_rs, src_l;
2100         unsigned char *src_p, *tgt_p;
2101         struct CPRB *cprb_p;
2102         struct CPRBX *cprbx_p;
2103
2104         src_p = 0;
2105         reply_code = 0;
2106         service_rc = 0;
2107         service_rs = 0;
2108         src_l = 0;
2109         switch (errh_p->type) {
2110         case TYPE82_RSP_CODE:
2111                 reply_code = errh_p->reply_code;
2112                 src_p = (unsigned char *)errh_p;
2113                 PRINTK("Hardware error: Type %02X Message Header: "
2114                        "%02x%02x%02x%02x%02x%02x%02x%02x\n",
2115                        errh_p->type,
2116                        src_p[0], src_p[1], src_p[2], src_p[3],
2117                        src_p[4], src_p[5], src_p[6], src_p[7]);
2118                 break;
2119         case TYPE84_RSP_CODE:
2120                 src_l = icaMsg_p->outputdatalength;
2121                 src_p = response + (int)t84h_p->len - src_l;
2122                 break;
2123         case TYPE86_RSP_CODE:
2124                 reply_code = t86m_p->header.reply_code;
2125                 if (reply_code != 0)
2126                         break;
2127                 cprb_p = (struct CPRB *)
2128                         (response + sizeof(struct type86_fmt2_msg));
2129                 cprbx_p = (struct CPRBX *) cprb_p;
2130                 if (cprb_p->cprb_ver_id != 0x02) {
2131                         le2toI(cprb_p->ccp_rtcode, &service_rc);
2132                         if (service_rc != 0) {
2133                                 le2toI(cprb_p->ccp_rscode, &service_rs);
2134                                 if ((service_rc == 8) && (service_rs == 66))
2135                                         PDEBUG("Bad block format on PCICC\n");
2136                                 else if ((service_rc == 8) && (service_rs == 65))
2137                                         PDEBUG("Probably an even modulus on "
2138                                                "PCICC\n");
2139                                 else if ((service_rc == 8) && (service_rs == 770)) {
2140                                         PDEBUG("Invalid key length on PCICC\n");
2141                                         unset_ext_bitlens();
2142                                         return REC_USE_PCICA;
2143                                 }
2144                                 else if ((service_rc == 8) && (service_rs == 783)) {
2145                                         PDEBUG("Extended bitlengths not enabled"
2146                                                "on PCICC\n");
2147                                         unset_ext_bitlens();
2148                                         return REC_USE_PCICA;
2149                                 }
2150                                 else
2151                                         PRINTK("service rc/rs (PCICC): %d/%d\n",
2152                                                service_rc, service_rs);
2153                                 return REC_OPERAND_INV;
2154                         }
2155                         src_p = (unsigned char *)cprb_p + sizeof(struct CPRB);
2156                         src_p += 4;
2157                         le2toI(src_p, &src_l);
2158                         src_l -= 2;
2159                         src_p += 2;
2160                 } else {
2161                         service_rc = (int)cprbx_p->ccp_rtcode;
2162                         if (service_rc != 0) {
2163                                 service_rs = (int) cprbx_p->ccp_rscode;
2164                                 if ((service_rc == 8) && (service_rs == 66))
2165                                         PDEBUG("Bad block format on PCIXCC\n");
2166                                 else if ((service_rc == 8) && (service_rs == 65))
2167                                         PDEBUG("Probably an even modulus on "
2168                                                "PCIXCC\n");
2169                                 else if ((service_rc == 8) && (service_rs == 770)) {
2170                                         PDEBUG("Invalid key length on PCIXCC\n");
2171                                         unset_ext_bitlens();
2172                                         return REC_USE_PCICA;
2173                                 }
2174                                 else if ((service_rc == 8) && (service_rs == 783)) {
2175                                         PDEBUG("Extended bitlengths not enabled"
2176                                                "on PCIXCC\n");
2177                                         unset_ext_bitlens();
2178                                         return REC_USE_PCICA;
2179                                 }
2180                                 else
2181                                         PRINTK("service rc/rs (PCIXCC): %d/%d\n",
2182                                                service_rc, service_rs);
2183                                 return REC_OPERAND_INV;
2184                         }
2185                         src_p = (unsigned char *)
2186                                 cprbx_p + sizeof(struct CPRBX);
2187                         src_p += 4;
2188                         src_l = (int)(*((short *) src_p));
2189                         src_l -= 2;
2190                         src_p += 2;
2191                 }
2192                 break;
2193         default:
2194                 src_p = (unsigned char *)errh_p;
2195                 PRINTK("Unrecognized Message Header: "
2196                        "%02x%02x%02x%02x%02x%02x%02x%02x\n",
2197                        src_p[0], src_p[1], src_p[2], src_p[3],
2198                        src_p[4], src_p[5], src_p[6], src_p[7]);
2199                 return REC_BAD_MESSAGE;
2200         }
2201
2202         if (reply_code)
2203                 switch (reply_code) {
2204                 case REP82_ERROR_OPERAND_INVALID:
2205                         return REC_OPERAND_INV;
2206                 case REP82_ERROR_OPERAND_SIZE:
2207                         return REC_OPERAND_SIZE;
2208                 case REP82_ERROR_EVEN_MOD_IN_OPND:
2209                         return REC_EVEN_MOD;
2210                 case REP82_ERROR_MESSAGE_TYPE:
2211                         return WRONG_DEVICE_TYPE;
2212                 case REP82_ERROR_TRANSPORT_FAIL:
2213                         PRINTKW("Transport failed (APFS = %02X%02X%02X%02X)\n",
2214                                 t86m_p->apfs[0], t86m_p->apfs[1],
2215                                 t86m_p->apfs[2], t86m_p->apfs[3]);
2216                         return REC_HARDWAR_ERR;
2217                 default:
2218                         PRINTKW("reply code = %d\n", reply_code);
2219                         return REC_HARDWAR_ERR;
2220                 }
2221
2222         if (service_rc != 0)
2223                 return REC_OPERAND_INV;
2224
2225         if ((src_l > icaMsg_p->outputdatalength) ||
2226             (src_l > RESPBUFFSIZE) ||
2227             (src_l <= 0))
2228                 return REC_OPERAND_SIZE;
2229
2230         PDEBUG("Length returned = %d\n", src_l);
2231         tgt_p = resp_buff + icaMsg_p->outputdatalength - src_l;
2232         memcpy(tgt_p, src_p, src_l);
2233         if ((errh_p->type == TYPE86_RSP_CODE) && (resp_buff < tgt_p)) {
2234                 memset(resp_buff, 0, icaMsg_p->outputdatalength - src_l);
2235                 if (pad_msg(resp_buff, icaMsg_p->outputdatalength, src_l))
2236                         return REC_INVALID_PAD;
2237         }
2238         *respbufflen_p = icaMsg_p->outputdatalength;
2239         if (*respbufflen_p == 0)
2240                 PRINTK("Zero *respbufflen_p\n");
2241
2242         return 0;
2243 }
2244