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