This commit was generated by cvs2svn to compensate for changes in r1129,
[linux-2.6.git] / drivers / s390 / crypto / z90hardware.c
index 8c8db43..4141919 100644 (file)
@@ -1,11 +1,11 @@
 /*
- *  linux/drivers/s390/misc/z90hardware.c
+ *  linux/drivers/s390/crypto/z90hardware.c
  *
- *  z90crypt 1.3.1
+ *  z90crypt 1.3.3
  *
- *  Copyright (C)  2001, 2004 IBM Corporation
+ *  Copyright (C)  2001, 2005 IBM Corporation
  *  Author(s): Robert Burroughs (burrough@us.ibm.com)
- *            Eric Rossman (edrossma@us.ibm.com)
+ *             Eric Rossman (edrossma@us.ibm.com)
  *
  *  Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
  *
@@ -16,7 +16,7 @@
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
 #include "z90crypt.h"
 #include "z90common.h"
 
-#define VERSION_Z90HARDWARE_C "$Revision: 1.19 $"
-
-char z90chardware_version[] __initdata =
-       "z90hardware.o (" VERSION_Z90HARDWARE_C "/"
-                         VERSION_Z90COMMON_H "/" VERSION_Z90CRYPT_H ")";
-
 struct cca_token_hdr {
        unsigned char  token_identifier;
        unsigned char  version;
@@ -224,7 +218,7 @@ struct type6_hdr {
        unsigned char right[4];
        unsigned char reserved3[2];
        unsigned char reserved4[2];
-       unsigned char pfs[4];
+       unsigned char apfs[4];
        unsigned int  offset1;
        unsigned int  offset2;
        unsigned int  offset3;
@@ -278,85 +272,11 @@ struct CPRB {
        unsigned char svr_name[8];
 };
 
-struct CPRBX {
-       unsigned short cprb_len;
-       unsigned char  cprb_ver_id;
-       unsigned char  pad_000[3];
-       unsigned char  func_id[2];
-       unsigned char  cprb_flags[4];
-       unsigned int   req_parml;
-       unsigned int   req_datal;
-       unsigned int   rpl_msgbl;
-       unsigned int   rpld_parml;
-       unsigned int   rpl_datal;
-       unsigned int   rpld_datal;
-       unsigned int   req_extbl;
-       unsigned char  pad_001[4];
-       unsigned int   rpld_extbl;
-       unsigned char  req_parmb[16];
-       unsigned char  req_datab[16];
-       unsigned char  rpl_parmb[16];
-       unsigned char  rpl_datab[16];
-       unsigned char  req_extb[16];
-       unsigned char  rpl_extb[16];
-       unsigned short ccp_rtcode;
-       unsigned short ccp_rscode;
-       unsigned int   mac_data_len;
-       unsigned char  logon_id[8];
-       unsigned char  mac_value[8];
-       unsigned char  mac_content_flgs;
-       unsigned char  pad_002;
-       unsigned short domain;
-       unsigned char  pad_003[12];
-       unsigned char  pad_004[36];
-};
-
 struct type6_msg {
        struct type6_hdr header;
        struct CPRB      CPRB;
 };
 
-union request_msg {
-       union  type4_msg t4msg;
-       struct type6_msg t6msg;
-};
-
-struct request_msg_ext {
-       int               q_nr;
-       unsigned char     *psmid;
-       union request_msg reqMsg;
-};
-
-struct type82_hdr {
-       unsigned char reserved1;
-       unsigned char type;
-       unsigned char reserved2[2];
-       unsigned char reply_code;
-       unsigned char reserved3[3];
-};
-
-#define TYPE82_RSP_CODE 0x82
-
-#define REPLY_ERROR_MACHINE_FAILURE  0x10
-#define REPLY_ERROR_PREEMPT_FAILURE  0x12
-#define REPLY_ERROR_CHECKPT_FAILURE  0x14
-#define REPLY_ERROR_MESSAGE_TYPE     0x20
-#define REPLY_ERROR_INVALID_COMM_CD  0x21
-#define REPLY_ERROR_INVALID_MSG_LEN  0x23
-#define REPLY_ERROR_RESERVD_FIELD    0x24
-#define REPLY_ERROR_FORMAT_FIELD     0x29
-#define REPLY_ERROR_INVALID_COMMAND  0x30
-#define REPLY_ERROR_MALFORMED_MSG    0x40
-#define REPLY_ERROR_RESERVED_FIELD   0x50
-#define REPLY_ERROR_WORD_ALIGNMENT   0x60
-#define REPLY_ERROR_MESSAGE_LENGTH   0x80
-#define REPLY_ERROR_OPERAND_INVALID  0x82
-#define REPLY_ERROR_OPERAND_SIZE     0x84
-#define REPLY_ERROR_EVEN_MOD_IN_OPND 0x85
-#define REPLY_ERROR_TRANSPORT_FAIL   0x90
-#define REPLY_ERROR_PACKET_TRUNCATED 0xA0
-#define REPLY_ERROR_ZERO_BUFFER_LEN  0xB0
-
 struct type86_hdr {
        unsigned char reserved1;
        unsigned char type;
@@ -370,7 +290,7 @@ struct type86_hdr {
 #define TYPE86_FMT2    0x02
 
 struct type86_fmt2_msg {
-       struct type86_hdr hdr;
+       struct type86_hdr header;
        unsigned char     reserved[4];
        unsigned char     apfs[4];
        unsigned int      count1;
@@ -379,7 +299,7 @@ struct type86_fmt2_msg {
        unsigned int      offset2;
        unsigned int      count3;
        unsigned int      offset3;
-       unsigned int      ount4;
+       unsigned int      count4;
        unsigned int      offset4;
 };
 
@@ -546,18 +466,32 @@ static struct CPRBX static_cprbx = {
         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
 };
 
-static struct function_and_rules_block static_pkd_function_and_rulesX = {
+static struct function_and_rules_block static_pkd_function_and_rulesX_MCL2 = {
        {0x50,0x44},
        {0x00,0x0A},
        {'P','K','C','S','-','1','.','2'}
 };
 
-static struct function_and_rules_block static_pke_function_and_rulesX = {
+static struct function_and_rules_block static_pke_function_and_rulesX_MCL2 = {
        {0x50,0x4B},
        {0x00,0x0A},
        {'Z','E','R','O','-','P','A','D'}
 };
 
+static struct function_and_rules_block static_pkd_function_and_rulesX = {
+       {0x50,0x44},
+       {0x00,0x0A},
+       {'Z','E','R','O','-','P','A','D'}
+};
+
+static struct function_and_rules_block static_pke_function_and_rulesX = {
+       {0x50,0x4B},
+       {0x00,0x0A},
+       {'M','R','P',' ',' ',' ',' ',' '}
+};
+
+static unsigned char static_PKE_function_code[2] = {0x50, 0x4B};
+
 struct T6_keyBlock_hdrX {
        unsigned short blen;
        unsigned short ulen;
@@ -701,18 +635,143 @@ static struct cca_public_sec static_cca_pub_sec = {
 
 #define FIXED_TYPE6_CR_LENX 0x000001E3
 
-#ifndef MAX_RESPONSE_SIZE
 #define MAX_RESPONSE_SIZE 0x00000710
 
 #define MAX_RESPONSEX_SIZE 0x0000077C
-#endif
 
 #define RESPONSE_CPRB_SIZE  0x000006B8
 #define RESPONSE_CPRBX_SIZE 0x00000724
 
-#define CALLER_HEADER 12
+struct type50_hdr {
+       u8    reserved1;
+       u8    msg_type_code;
+       u16   msg_len;
+       u8    reserved2;
+       u8    ignored;
+       u16   reserved3;
+};
 
-static unsigned char static_PKE_function_code[2] = {0x50, 0x4B};
+#define TYPE50_TYPE_CODE 0x50
+
+#define TYPE50_MEB1_LEN (sizeof(struct type50_meb1_msg))
+#define TYPE50_MEB2_LEN (sizeof(struct type50_meb2_msg))
+#define TYPE50_CRB1_LEN (sizeof(struct type50_crb1_msg))
+#define TYPE50_CRB2_LEN (sizeof(struct type50_crb2_msg))
+
+#define TYPE50_MEB1_FMT 0x0001
+#define TYPE50_MEB2_FMT 0x0002
+#define TYPE50_CRB1_FMT 0x0011
+#define TYPE50_CRB2_FMT 0x0012
+
+struct type50_meb1_msg {
+       struct type50_hdr       header;
+       u16                     keyblock_type;
+       u8                      reserved[6];
+       u8                      exponent[128];
+       u8                      modulus[128];
+       u8                      message[128];
+};
+
+struct type50_meb2_msg {
+       struct type50_hdr       header;
+       u16                     keyblock_type;
+       u8                      reserved[6];
+       u8                      exponent[256];
+       u8                      modulus[256];
+       u8                      message[256];
+};
+
+struct type50_crb1_msg {
+       struct type50_hdr       header;
+       u16                     keyblock_type;
+       u8                      reserved[6];
+       u8                      p[64];
+       u8                      q[64];
+       u8                      dp[64];
+       u8                      dq[64];
+       u8                      u[64];
+       u8                      message[128];
+};
+
+struct type50_crb2_msg {
+       struct type50_hdr       header;
+       u16                     keyblock_type;
+       u8                      reserved[6];
+       u8                      p[128];
+       u8                      q[128];
+       u8                      dp[128];
+       u8                      dq[128];
+       u8                      u[128];
+       u8                      message[256];
+};
+
+union type50_msg {
+       struct type50_meb1_msg meb1;
+       struct type50_meb2_msg meb2;
+       struct type50_crb1_msg crb1;
+       struct type50_crb2_msg crb2;
+};
+
+struct type80_hdr {
+       u8      reserved1;
+       u8      type;
+       u16     len;
+       u8      code;
+       u8      reserved2[3];
+       u8      reserved3[8];
+};
+
+#define TYPE80_RSP_CODE 0x80
+
+struct error_hdr {
+       unsigned char reserved1;
+       unsigned char type;
+       unsigned char reserved2[2];
+       unsigned char reply_code;
+       unsigned char reserved3[3];
+};
+
+#define TYPE82_RSP_CODE 0x82
+#define TYPE88_RSP_CODE 0x88
+
+#define REP82_ERROR_MACHINE_FAILURE  0x10
+#define REP82_ERROR_PREEMPT_FAILURE  0x12
+#define REP82_ERROR_CHECKPT_FAILURE  0x14
+#define REP82_ERROR_MESSAGE_TYPE     0x20
+#define REP82_ERROR_INVALID_COMM_CD  0x21
+#define REP82_ERROR_INVALID_MSG_LEN  0x23
+#define REP82_ERROR_RESERVD_FIELD    0x24
+#define REP82_ERROR_FORMAT_FIELD     0x29
+#define REP82_ERROR_INVALID_COMMAND  0x30
+#define REP82_ERROR_MALFORMED_MSG    0x40
+#define REP82_ERROR_RESERVED_FIELDO  0x50
+#define REP82_ERROR_WORD_ALIGNMENT   0x60
+#define REP82_ERROR_MESSAGE_LENGTH   0x80
+#define REP82_ERROR_OPERAND_INVALID  0x82
+#define REP82_ERROR_OPERAND_SIZE     0x84
+#define REP82_ERROR_EVEN_MOD_IN_OPND 0x85
+#define REP82_ERROR_RESERVED_FIELD   0x88
+#define REP82_ERROR_TRANSPORT_FAIL   0x90
+#define REP82_ERROR_PACKET_TRUNCATED 0xA0
+#define REP82_ERROR_ZERO_BUFFER_LEN  0xB0
+
+#define REP88_ERROR_MODULE_FAILURE   0x10
+#define REP88_ERROR_MODULE_TIMEOUT   0x11
+#define REP88_ERROR_MODULE_NOTINIT   0x13
+#define REP88_ERROR_MODULE_NOTAVAIL  0x14
+#define REP88_ERROR_MODULE_DISABLED  0x15
+#define REP88_ERROR_MODULE_IN_DIAGN  0x17
+#define REP88_ERROR_FASTPATH_DISABLD 0x19
+#define REP88_ERROR_MESSAGE_TYPE     0x20
+#define REP88_ERROR_MESSAGE_MALFORMD 0x22
+#define REP88_ERROR_MESSAGE_LENGTH   0x23
+#define REP88_ERROR_RESERVED_FIELD   0x24
+#define REP88_ERROR_KEY_TYPE         0x34
+#define REP88_ERROR_INVALID_KEY      0x82
+#define REP88_ERROR_OPERAND          0x84
+#define REP88_ERROR_OPERAND_EVEN_MOD 0x85
+
+#define CALLER_HEADER 12
 
 static inline int
 testq(int q_nr, int *q_depth, int *dev_type, struct ap_status_word *stat)
@@ -720,7 +779,7 @@ testq(int q_nr, int *q_depth, int *dev_type, struct ap_status_word *stat)
        int ccode;
 
        asm volatile
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
        ("      llgfr   0,%4            \n"
         "      slgr    1,1             \n"
         "      lgr     2,1             \n"
@@ -790,7 +849,7 @@ resetq(int q_nr, struct ap_status_word *stat_p)
        int ccode;
 
        asm volatile
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
        ("      llgfr   0,%2            \n"
         "      lghi    1,1             \n"
         "      sll     1,24            \n"
@@ -856,7 +915,7 @@ sen(int msg_len, unsigned char *msg_ext, struct ap_status_word *stat)
        int ccode;
 
        asm volatile
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
        ("      lgr     6,%3            \n"
         "      llgfr   7,%2            \n"
         "      llgt    0,0(6)          \n"
@@ -935,7 +994,7 @@ rec(int q_nr, int buff_l, unsigned char *rsp, unsigned char *id,
        int ccode;
 
        asm volatile
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
        ("      llgfr   0,%2            \n"
         "      lgr     3,%4            \n"
         "      lgr     6,%3            \n"
@@ -1062,11 +1121,6 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type)
                        stat = HD_ONLINE;
                        *q_depth = t_depth + 1;
                        switch (t_dev_type) {
-                       case OTHER_HW:
-                       case OTHER2_HW:
-                               stat = HD_NOT_THERE;
-                               *dev_type = NILDEV;
-                               break;
                        case PCICA_HW:
                                *dev_type = PCICA;
                                break;
@@ -1074,7 +1128,13 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type)
                                *dev_type = PCICC;
                                break;
                        case PCIXCC_HW:
-                               *dev_type = PCIXCC;
+                               *dev_type = PCIXCC_UNK;
+                               break;
+                       case CEX2C_HW:
+                               *dev_type = CEX2C;
+                               break;
+                       case CEX2A_HW:
+                               *dev_type = CEX2A;
                                break;
                        default:
                                *dev_type = NILDEV;
@@ -1133,6 +1193,7 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type)
                default:
                        stat = HD_NOT_THERE;
                        break_out = 1;
+                       break;
                }
                if (break_out)
                        break;
@@ -1170,18 +1231,11 @@ reset_device(int deviceNr, int cdx, int resetNr)
                        switch (stat_word.response_code) {
                        case AP_RESPONSE_NORMAL:
                                stat = DEV_ONLINE;
-                               if (stat_word.q_stat_flags &
-                                   AP_Q_STATUS_EMPTY)
+                               if (stat_word.q_stat_flags & AP_Q_STATUS_EMPTY)
                                        break_out = 1;
                                break;
                        case AP_RESPONSE_Q_NOT_AVAIL:
-                               stat = DEV_GONE;
-                               break_out = 1;
-                               break;
                        case AP_RESPONSE_DECONFIGURED:
-                               stat = DEV_GONE;
-                               break_out = 1;
-                               break;
                        case AP_RESPONSE_CHECKSTOPPED:
                                stat = DEV_GONE;
                                break_out = 1;
@@ -1195,6 +1249,7 @@ reset_device(int deviceNr, int cdx, int resetNr)
                default:
                        stat = DEV_GONE;
                        break_out = 1;
+                       break;
                }
                if (break_out == 1)
                        break;
@@ -1237,9 +1292,9 @@ send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext)
        struct ap_status_word stat_word;
        enum devstat stat;
        int ccode;
+       u32 *q_nr_p = (u32 *)msg_ext;
 
-       ((struct request_msg_ext *) msg_ext)->q_nr =
-               (dev_nr << SKIP_BITL) + cdx;
+       *q_nr_p = (dev_nr << SKIP_BITL) + cdx;
        PDEBUG("msg_len passed to sen: %d\n", msg_len);
        PDEBUG("q number passed to sen: %02x%02x%02x%02x\n",
               msg_ext[0], msg_ext[1], msg_ext[2], msg_ext[3]);
@@ -1251,7 +1306,7 @@ send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext)
               msg_ext[0], msg_ext[1], msg_ext[2], msg_ext[3],
               msg_ext[4], msg_ext[5], msg_ext[6], msg_ext[7],
               msg_ext[8], msg_ext[9], msg_ext[10], msg_ext[11]);
-       print_buffer(msg_ext+12, msg_len);
+       print_buffer(msg_ext+CALLER_HEADER, msg_len);
 #endif
 
        ccode = sen(msg_len, msg_ext, &stat_word);
@@ -1283,14 +1338,15 @@ send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext)
                break;
        default:
                stat = DEV_GONE;
+               break;
        }
 
        return stat;
 }
 
 enum devstat
-receive_from_AP(int dev_nr, int cdx, int resplen,
-               unsigned char *resp, unsigned char *psmid)
+receive_from_AP(int dev_nr, int cdx, int resplen, unsigned char *resp,
+               unsigned char *psmid)
 {
        int ccode;
        struct ap_status_word stat_word;
@@ -1543,6 +1599,7 @@ ICAMEX_msg_to_type6MEX_de_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx,
        struct type6_hdr *tp6Hdr_p;
        struct CPRB *cprb_p;
        struct cca_private_ext_ME *key_p;
+       static int deprecated_msg_count = 0;
 
        mod_len = icaMsg_p->inputdatalength;
        tmp_size = FIXED_TYPE6_ME_LEN + mod_len;
@@ -1593,13 +1650,19 @@ ICAMEX_msg_to_type6MEX_de_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx,
                return SEN_USER_ERROR;
 
        if (is_common_public_key(temp, mod_len)) {
-               PRINTK("Common public key used for modex decrypt\n");
+               if (deprecated_msg_count < 20) {
+                       PRINTK("Common public key used for modex decrypt\n");
+                       deprecated_msg_count++;
+                       if (deprecated_msg_count == 20)
+                               PRINTK("No longer issuing messages about common"
+                                      " public key for modex decrypt.\n");
+               }
                return SEN_NOT_AVAIL;
        }
 
        temp = key_p->pvtMESec.modulus + sizeof(key_p->pvtMESec.modulus)
               - mod_len;
-       if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len) != 0)
+       if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len))
                return SEN_RELEASED;
        if (is_empty(temp, mod_len))
                return SEN_USER_ERROR;
@@ -1617,24 +1680,33 @@ ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx,
 {
        int mod_len, vud_len, exp_len, key_len;
        int pad_len, tmp_size, total_CPRB_len, parmBlock_l, i;
-       unsigned char temp_exp[256], *exp_p, *temp;
+       unsigned char *temp_exp, *exp_p, *temp;
        struct type6_hdr *tp6Hdr_p;
        struct CPRB *cprb_p;
        struct cca_public_key *key_p;
        struct T6_keyBlock_hdr *keyb_p;
 
+       temp_exp = kmalloc(256, GFP_KERNEL);
+       if (!temp_exp)
+               return EGETBUFF;
        mod_len = icaMsg_p->inputdatalength;
-       if (copy_from_user(temp_exp, icaMsg_p->b_key, mod_len))
+       if (copy_from_user(temp_exp, icaMsg_p->b_key, mod_len)) {
+               kfree(temp_exp);
                return SEN_RELEASED;
-       if (is_empty(temp_exp, mod_len))
+       }
+       if (is_empty(temp_exp, mod_len)) {
+               kfree(temp_exp);
                return SEN_USER_ERROR;
+       }
 
        exp_p = temp_exp;
        for (i = 0; i < mod_len; i++)
                if (exp_p[i])
                        break;
-       if (i >= mod_len)
+       if (i >= mod_len) {
+               kfree(temp_exp);
                return SEN_USER_ERROR;
+       }
 
        exp_len = mod_len - i;
        exp_p += i;
@@ -1665,17 +1737,25 @@ ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx,
                 sizeof(struct function_and_rules_block));
        temp += sizeof(struct function_and_rules_block);
        temp += 2;
-       if (copy_from_user(temp, icaMsg_p->inputdata, mod_len))
+       if (copy_from_user(temp, icaMsg_p->inputdata, mod_len)) {
+               kfree(temp_exp);
                return SEN_RELEASED;
-       if (is_empty(temp, mod_len))
+       }
+       if (is_empty(temp, mod_len)) {
+               kfree(temp_exp);
                return SEN_USER_ERROR;
-       if (temp[0] != 0x00 || temp[1] != 0x02)
+       }
+       if ((temp[0] != 0x00) || (temp[1] != 0x02)) {
+               kfree(temp_exp);
                return SEN_NOT_AVAIL;
+       }
        for (i = 2; i < mod_len; i++)
                if (temp[i] == 0x00)
                        break;
-       if ((i < 9) || (i > (mod_len - 2)))
+       if ((i < 9) || (i > (mod_len - 2))) {
+               kfree(temp_exp);
                return SEN_NOT_AVAIL;
+       }
        pad_len = i + 1;
        vud_len = mod_len - pad_len;
        memmove(temp, temp+pad_len, vud_len);
@@ -1689,6 +1769,7 @@ ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx,
        key_p = (struct cca_public_key *)temp;
        temp = key_p->pubSec.exponent;
        memcpy(temp, exp_p, exp_len);
+       kfree(temp_exp);
        temp += exp_len;
        if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len))
                return SEN_RELEASED;
@@ -1697,7 +1778,7 @@ ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx,
        key_p->pubSec.modulus_bit_len = 8 * mod_len;
        key_p->pubSec.modulus_byte_len = mod_len;
        key_p->pubSec.exponent_len = exp_len;
-       key_p->pubSec.section_length = 12 + mod_len + exp_len;
+       key_p->pubSec.section_length = CALLER_HEADER + mod_len + exp_len;
        key_len = key_p->pubSec.section_length + sizeof(struct cca_token_hdr);
        key_p->pubHdr.token_length = key_len;
        key_len += 4;
@@ -1824,27 +1905,37 @@ ICACRT_msg_to_type6CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx,
 
 static int
 ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx,
-                           int *z90cMsg_l_p, struct type6_msg *z90cMsg_p)
+                           int *z90cMsg_l_p, struct type6_msg *z90cMsg_p,
+                           int dev_type)
 {
        int mod_len, exp_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l;
        int key_len, i;
-       unsigned char temp_exp[256], *tgt_p, *temp, *exp_p;
+       unsigned char *temp_exp, *tgt_p, *temp, *exp_p;
        struct type6_hdr *tp6Hdr_p;
        struct CPRBX *cprbx_p;
        struct cca_public_key *key_p;
        struct T6_keyBlock_hdrX *keyb_p;
 
+       temp_exp = kmalloc(256, GFP_KERNEL);
+       if (!temp_exp)
+               return EGETBUFF;
        mod_len = icaMsg_p->inputdatalength;
-       if (copy_from_user(temp_exp, icaMsg_p->b_key, mod_len))
+       if (copy_from_user(temp_exp, icaMsg_p->b_key, mod_len)) {
+               kfree(temp_exp);
                return SEN_RELEASED;
-       if (is_empty(temp_exp, mod_len))
+       }
+       if (is_empty(temp_exp, mod_len)) {
+               kfree(temp_exp);
                return SEN_USER_ERROR;
+       }
        exp_p = temp_exp;
        for (i = 0; i < mod_len; i++)
                if (exp_p[i])
                        break;
-       if (i >= mod_len)
+       if (i >= mod_len) {
+               kfree(temp_exp);
                return SEN_USER_ERROR;
+       }
        exp_len = mod_len - i;
        exp_p += i;
        PDEBUG("exp_len after computation: %08x\n", exp_len);
@@ -1867,15 +1958,23 @@ ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx,
        cprbx_p->domain = (unsigned short)cdx;
        cprbx_p->rpl_msgbl = RESPONSE_CPRBX_SIZE;
        tgt_p += sizeof(struct CPRBX);
-       memcpy(tgt_p, &static_pke_function_and_rulesX,
-              sizeof(struct function_and_rules_block));
+       if (dev_type == PCIXCC_MCL2)
+               memcpy(tgt_p, &static_pke_function_and_rulesX_MCL2,
+                      sizeof(struct function_and_rules_block));
+       else
+               memcpy(tgt_p, &static_pke_function_and_rulesX,
+                      sizeof(struct function_and_rules_block));
        tgt_p += sizeof(struct function_and_rules_block);
 
        tgt_p += 2;
-       if (copy_from_user(tgt_p, icaMsg_p->inputdata, mod_len))
-             return SEN_RELEASED;
-       if (is_empty(tgt_p, mod_len))
-             return SEN_USER_ERROR;
+       if (copy_from_user(tgt_p, icaMsg_p->inputdata, mod_len)) {
+               kfree(temp_exp);
+               return SEN_RELEASED;
+       }
+       if (is_empty(tgt_p, mod_len)) {
+               kfree(temp_exp);
+               return SEN_USER_ERROR;
+       }
        tgt_p -= 2;
        *((short *)tgt_p) = (short) vud_len;
        tgt_p += vud_len;
@@ -1885,15 +1984,16 @@ ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx,
        key_p = (struct cca_public_key *)tgt_p;
        temp = key_p->pubSec.exponent;
        memcpy(temp, exp_p, exp_len);
+       kfree(temp_exp);
        temp += exp_len;
        if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len))
-             return SEN_RELEASED;
+               return SEN_RELEASED;
        if (is_empty(temp, mod_len))
-             return SEN_USER_ERROR;
+               return SEN_USER_ERROR;
        key_p->pubSec.modulus_bit_len = 8 * mod_len;
        key_p->pubSec.modulus_byte_len = mod_len;
        key_p->pubSec.exponent_len = exp_len;
-       key_p->pubSec.section_length = 12 + mod_len + exp_len;
+       key_p->pubSec.section_length = CALLER_HEADER + mod_len + exp_len;
        key_len = key_p->pubSec.section_length + sizeof(struct cca_token_hdr);
        key_p->pubHdr.token_length = key_len;
        key_len += 4;
@@ -1908,7 +2008,8 @@ ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx,
 
 static int
 ICACRT_msg_to_type6CRT_msgX(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx,
-                           int *z90cMsg_l_p, struct type6_msg *z90cMsg_p)
+                           int *z90cMsg_l_p, struct type6_msg *z90cMsg_p,
+                           int dev_type)
 {
        int mod_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l, short_len;
        int long_len, pad_len, keyPartsLen, tmp_l;
@@ -1943,8 +2044,12 @@ ICACRT_msg_to_type6CRT_msgX(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx,
        cprbx_p->req_parml = parmBlock_l;
        cprbx_p->rpl_msgbl = parmBlock_l;
        tgt_p += sizeof(struct CPRBX);
-       memcpy(tgt_p, &static_pkd_function_and_rulesX,
-              sizeof(struct function_and_rules_block));
+       if (dev_type == PCIXCC_MCL2)
+               memcpy(tgt_p, &static_pkd_function_and_rulesX_MCL2,
+                      sizeof(struct function_and_rules_block));
+       else
+               memcpy(tgt_p, &static_pkd_function_and_rulesX,
+                      sizeof(struct function_and_rules_block));
        tgt_p += sizeof(struct function_and_rules_block);
        *((short *)tgt_p) = (short) vud_len;
        tgt_p += 2;
@@ -2015,6 +2120,177 @@ ICACRT_msg_to_type6CRT_msgX(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx,
        return 0;
 }
 
+static int
+ICAMEX_msg_to_type50MEX_msg(struct ica_rsa_modexpo *icaMex_p, int *z90cMsg_l_p,
+                           union type50_msg *z90cMsg_p)
+{
+       int mod_len, msg_size, mod_tgt_len, exp_tgt_len, inp_tgt_len;
+       unsigned char *mod_tgt, *exp_tgt, *inp_tgt;
+       union type50_msg *tmp_type50_msg;
+
+       mod_len = icaMex_p->inputdatalength;
+
+       msg_size = ((mod_len <= 128) ? TYPE50_MEB1_LEN : TYPE50_MEB2_LEN) +
+                   CALLER_HEADER;
+
+       memset(z90cMsg_p, 0, msg_size);
+
+       tmp_type50_msg = (union type50_msg *)
+               ((unsigned char *) z90cMsg_p + CALLER_HEADER);
+
+       tmp_type50_msg->meb1.header.msg_type_code = TYPE50_TYPE_CODE;
+
+       if (mod_len <= 128) {
+               tmp_type50_msg->meb1.header.msg_len = TYPE50_MEB1_LEN;
+               tmp_type50_msg->meb1.keyblock_type = TYPE50_MEB1_FMT;
+               mod_tgt = tmp_type50_msg->meb1.modulus;
+               mod_tgt_len = sizeof(tmp_type50_msg->meb1.modulus);
+               exp_tgt = tmp_type50_msg->meb1.exponent;
+               exp_tgt_len = sizeof(tmp_type50_msg->meb1.exponent);
+               inp_tgt = tmp_type50_msg->meb1.message;
+               inp_tgt_len = sizeof(tmp_type50_msg->meb1.message);
+       } else {
+               tmp_type50_msg->meb2.header.msg_len = TYPE50_MEB2_LEN;
+               tmp_type50_msg->meb2.keyblock_type = TYPE50_MEB2_FMT;
+               mod_tgt = tmp_type50_msg->meb2.modulus;
+               mod_tgt_len = sizeof(tmp_type50_msg->meb2.modulus);
+               exp_tgt = tmp_type50_msg->meb2.exponent;
+               exp_tgt_len = sizeof(tmp_type50_msg->meb2.exponent);
+               inp_tgt = tmp_type50_msg->meb2.message;
+               inp_tgt_len = sizeof(tmp_type50_msg->meb2.message);
+       }
+
+       mod_tgt += (mod_tgt_len - mod_len);
+       if (copy_from_user(mod_tgt, icaMex_p->n_modulus, mod_len))
+               return SEN_RELEASED;
+       if (is_empty(mod_tgt, mod_len))
+               return SEN_USER_ERROR;
+       exp_tgt += (exp_tgt_len - mod_len);
+       if (copy_from_user(exp_tgt, icaMex_p->b_key, mod_len))
+               return SEN_RELEASED;
+       if (is_empty(exp_tgt, mod_len))
+               return SEN_USER_ERROR;
+       inp_tgt += (inp_tgt_len - mod_len);
+       if (copy_from_user(inp_tgt, icaMex_p->inputdata, mod_len))
+               return SEN_RELEASED;
+       if (is_empty(inp_tgt, mod_len))
+               return SEN_USER_ERROR;
+
+       *z90cMsg_l_p = msg_size - CALLER_HEADER;
+
+       return 0;
+}
+
+static int
+ICACRT_msg_to_type50CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p,
+                           int *z90cMsg_l_p, union type50_msg *z90cMsg_p)
+{
+       int mod_len, short_len, long_len, tmp_size, p_tgt_len, q_tgt_len,
+           dp_tgt_len, dq_tgt_len, u_tgt_len, inp_tgt_len, long_offset;
+       unsigned char *p_tgt, *q_tgt, *dp_tgt, *dq_tgt, *u_tgt, *inp_tgt,
+                     temp[8];
+       union type50_msg *tmp_type50_msg;
+
+       mod_len = icaMsg_p->inputdatalength;
+       short_len = mod_len / 2;
+       long_len = mod_len / 2 + 8;
+       long_offset = 0;
+
+       if (long_len > 128) {
+               memset(temp, 0x00, sizeof(temp));
+               if (copy_from_user(temp, icaMsg_p->np_prime, long_len-128))
+                       return SEN_RELEASED;
+               if (!is_empty(temp, 8))
+                       return SEN_NOT_AVAIL;
+               if (copy_from_user(temp, icaMsg_p->bp_key, long_len-128))
+                       return SEN_RELEASED;
+               if (!is_empty(temp, 8))
+                       return SEN_NOT_AVAIL;
+               if (copy_from_user(temp, icaMsg_p->u_mult_inv, long_len-128))
+                       return SEN_RELEASED;
+               if (!is_empty(temp, 8))
+                       return SEN_NOT_AVAIL;
+               long_offset = long_len - 128;
+               long_len = 128;
+       }
+
+       tmp_size = ((mod_len <= 128) ? TYPE50_CRB1_LEN : TYPE50_CRB2_LEN) +
+                   CALLER_HEADER;
+
+       memset(z90cMsg_p, 0, tmp_size);
+
+       tmp_type50_msg = (union type50_msg *)
+               ((unsigned char *) z90cMsg_p + CALLER_HEADER);
+
+       tmp_type50_msg->crb1.header.msg_type_code = TYPE50_TYPE_CODE;
+       if (long_len <= 64) {
+               tmp_type50_msg->crb1.header.msg_len = TYPE50_CRB1_LEN;
+               tmp_type50_msg->crb1.keyblock_type = TYPE50_CRB1_FMT;
+               p_tgt = tmp_type50_msg->crb1.p;
+               p_tgt_len = sizeof(tmp_type50_msg->crb1.p);
+               q_tgt = tmp_type50_msg->crb1.q;
+               q_tgt_len = sizeof(tmp_type50_msg->crb1.q);
+               dp_tgt = tmp_type50_msg->crb1.dp;
+               dp_tgt_len = sizeof(tmp_type50_msg->crb1.dp);
+               dq_tgt = tmp_type50_msg->crb1.dq;
+               dq_tgt_len = sizeof(tmp_type50_msg->crb1.dq);
+               u_tgt = tmp_type50_msg->crb1.u;
+               u_tgt_len = sizeof(tmp_type50_msg->crb1.u);
+               inp_tgt = tmp_type50_msg->crb1.message;
+               inp_tgt_len = sizeof(tmp_type50_msg->crb1.message);
+       } else {
+               tmp_type50_msg->crb2.header.msg_len = TYPE50_CRB2_LEN;
+               tmp_type50_msg->crb2.keyblock_type = TYPE50_CRB2_FMT;
+               p_tgt = tmp_type50_msg->crb2.p;
+               p_tgt_len = sizeof(tmp_type50_msg->crb2.p);
+               q_tgt = tmp_type50_msg->crb2.q;
+               q_tgt_len = sizeof(tmp_type50_msg->crb2.q);
+               dp_tgt = tmp_type50_msg->crb2.dp;
+               dp_tgt_len = sizeof(tmp_type50_msg->crb2.dp);
+               dq_tgt = tmp_type50_msg->crb2.dq;
+               dq_tgt_len = sizeof(tmp_type50_msg->crb2.dq);
+               u_tgt = tmp_type50_msg->crb2.u;
+               u_tgt_len = sizeof(tmp_type50_msg->crb2.u);
+               inp_tgt = tmp_type50_msg->crb2.message;
+               inp_tgt_len = sizeof(tmp_type50_msg->crb2.message);
+       }
+
+       p_tgt += (p_tgt_len - long_len);
+       if (copy_from_user(p_tgt, icaMsg_p->np_prime + long_offset, long_len))
+               return SEN_RELEASED;
+       if (is_empty(p_tgt, long_len))
+               return SEN_USER_ERROR;
+       q_tgt += (q_tgt_len - short_len);
+       if (copy_from_user(q_tgt, icaMsg_p->nq_prime, short_len))
+               return SEN_RELEASED;
+       if (is_empty(q_tgt, short_len))
+               return SEN_USER_ERROR;
+       dp_tgt += (dp_tgt_len - long_len);
+       if (copy_from_user(dp_tgt, icaMsg_p->bp_key + long_offset, long_len))
+               return SEN_RELEASED;
+       if (is_empty(dp_tgt, long_len))
+               return SEN_USER_ERROR;
+       dq_tgt += (dq_tgt_len - short_len);
+       if (copy_from_user(dq_tgt, icaMsg_p->bq_key, short_len))
+               return SEN_RELEASED;
+       if (is_empty(dq_tgt, short_len))
+               return SEN_USER_ERROR;
+       u_tgt += (u_tgt_len - long_len);
+       if (copy_from_user(u_tgt, icaMsg_p->u_mult_inv + long_offset, long_len))
+               return SEN_RELEASED;
+       if (is_empty(u_tgt, long_len))
+               return SEN_USER_ERROR;
+       inp_tgt += (inp_tgt_len - mod_len);
+       if (copy_from_user(inp_tgt, icaMsg_p->inputdata, mod_len))
+               return SEN_RELEASED;
+       if (is_empty(inp_tgt, mod_len))
+               return SEN_USER_ERROR;
+
+       *z90cMsg_l_p = tmp_size - CALLER_HEADER;
+
+       return 0;
+}
+
 int
 convert_request(unsigned char *buffer, int func, unsigned short function,
                int cdx, int dev_type, int *msg_l_p, unsigned char *msg_p)
@@ -2043,29 +2319,57 @@ convert_request(unsigned char *buffer, int func, unsigned short function,
                                (struct ica_rsa_modexpo *) buffer,
                                cdx, msg_l_p, (struct type6_msg *) msg_p);
        }
-       if (dev_type == PCIXCC) {
+       if ((dev_type == PCIXCC_MCL2) ||
+           (dev_type == PCIXCC_MCL3) ||
+           (dev_type == CEX2C)) {
                if (func == ICARSACRT)
                        return ICACRT_msg_to_type6CRT_msgX(
                                (struct ica_rsa_modexpo_crt *) buffer,
-                               cdx, msg_l_p, (struct type6_msg *) msg_p);
+                               cdx, msg_l_p, (struct type6_msg *) msg_p,
+                               dev_type);
                else
                        return ICAMEX_msg_to_type6MEX_msgX(
                                (struct ica_rsa_modexpo *) buffer,
-                               cdx, msg_l_p, (struct type6_msg *) msg_p);
+                               cdx, msg_l_p, (struct type6_msg *) msg_p,
+                               dev_type);
+       }
+       if (dev_type == CEX2A) {
+               if (func == ICARSACRT)
+                       return ICACRT_msg_to_type50CRT_msg(
+                               (struct ica_rsa_modexpo_crt *) buffer,
+                               msg_l_p, (union type50_msg *) msg_p);
+               else
+                       return ICAMEX_msg_to_type50MEX_msg(
+                               (struct ica_rsa_modexpo *) buffer,
+                               msg_l_p, (union type50_msg *) msg_p);
        }
 
        return 0;
 }
 
+int ext_bitlens_msg_count = 0;
+static inline void
+unset_ext_bitlens(void)
+{
+       if (!ext_bitlens_msg_count) {
+               PRINTK("Unable to use coprocessors for extended bitlengths. "
+                      "Using PCICAs/CEX2As (if present) for extended "
+                      "bitlengths. This is not an error.\n");
+               ext_bitlens_msg_count++;
+       }
+       ext_bitlens = 0;
+}
+
 int
 convert_response(unsigned char *response, unsigned char *buffer,
                 int *respbufflen_p, unsigned char *resp_buff)
 {
        struct ica_rsa_modexpo *icaMsg_p = (struct ica_rsa_modexpo *) buffer;
-       struct type82_hdr *t82h_p = (struct type82_hdr *) response;
+       struct error_hdr *errh_p = (struct error_hdr *) response;
+       struct type80_hdr *t80h_p = (struct type80_hdr *) response;
        struct type84_hdr *t84h_p = (struct type84_hdr *) response;
-       struct type86_hdr *t86h_p = (struct type86_hdr *) response;
-       int rv, reply_code, service_rc, service_rs, src_l;
+       struct type86_fmt2_msg *t86m_p =  (struct type86_fmt2_msg *) response;
+       int reply_code, service_rc, service_rs, src_l;
        unsigned char *src_p, *tgt_p;
        struct CPRB *cprb_p;
        struct CPRBX *cprbx_p;
@@ -2075,31 +2379,29 @@ convert_response(unsigned char *response, unsigned char *buffer,
        service_rc = 0;
        service_rs = 0;
        src_l = 0;
-       rv = 0;
-       switch (t82h_p->type) {
+       switch (errh_p->type) {
        case TYPE82_RSP_CODE:
-               reply_code = t82h_p->reply_code;
-               rv = 4;
-               src_p = (unsigned char *)t82h_p;
-               PRINTK("Hardware error: Type 82 Message Header: "
+       case TYPE88_RSP_CODE:
+               reply_code = errh_p->reply_code;
+               src_p = (unsigned char *)errh_p;
+               PRINTK("Hardware error: Type %02X Message Header: "
                       "%02x%02x%02x%02x%02x%02x%02x%02x\n",
+                      errh_p->type,
                       src_p[0], src_p[1], src_p[2], src_p[3],
                       src_p[4], src_p[5], src_p[6], src_p[7]);
                break;
+       case TYPE80_RSP_CODE:
+               src_l = icaMsg_p->outputdatalength;
+               src_p = response + (int)t80h_p->len - src_l;
+               break;
        case TYPE84_RSP_CODE:
                src_l = icaMsg_p->outputdatalength;
                src_p = response + (int)t84h_p->len - src_l;
                break;
        case TYPE86_RSP_CODE:
-               reply_code = t86h_p->reply_code;
-               if (t86h_p->format != TYPE86_FMT2) {
-                       rv = 4;
-                       break;
-               }
-               if (reply_code != 0) {
-                       rv = 4;
+               reply_code = t86m_p->header.reply_code;
+               if (reply_code != 0)
                        break;
-               }
                cprb_p = (struct CPRB *)
                        (response + sizeof(struct type86_fmt2_msg));
                cprbx_p = (struct CPRBX *) cprb_p;
@@ -2108,11 +2410,25 @@ convert_response(unsigned char *response, unsigned char *buffer,
                        if (service_rc != 0) {
                                le2toI(cprb_p->ccp_rscode, &service_rs);
                                if ((service_rc == 8) && (service_rs == 66))
-                                       PDEBUG("8/66 on PCICC\n");
+                                       PDEBUG("Bad block format on PCICC\n");
+                               else if ((service_rc == 8) && (service_rs == 65))
+                                       PDEBUG("Probably an even modulus on "
+                                              "PCICC\n");
+                               else if ((service_rc == 8) && (service_rs == 770)) {
+                                       PDEBUG("Invalid key length on PCICC\n");
+                                       unset_ext_bitlens();
+                                       return REC_USE_PCICA;
+                               }
+                               else if ((service_rc == 8) && (service_rs == 783)) {
+                                       PDEBUG("Extended bitlengths not enabled"
+                                              "on PCICC\n");
+                                       unset_ext_bitlens();
+                                       return REC_USE_PCICA;
+                               }
                                else
-                                       PRINTK("service rc/rs: %d/%d\n",
+                                       PRINTK("service rc/rs (PCICC): %d/%d\n",
                                               service_rc, service_rs);
-                               rv = 8;
+                               return REC_OPERAND_INV;
                        }
                        src_p = (unsigned char *)cprb_p + sizeof(struct CPRB);
                        src_p += 4;
@@ -2124,11 +2440,25 @@ convert_response(unsigned char *response, unsigned char *buffer,
                        if (service_rc != 0) {
                                service_rs = (int) cprbx_p->ccp_rscode;
                                if ((service_rc == 8) && (service_rs == 66))
-                                       PDEBUG("8/66 on PCIXCC\n");
+                                       PDEBUG("Bad block format on PCIXCC\n");
+                               else if ((service_rc == 8) && (service_rs == 65))
+                                       PDEBUG("Probably an even modulus on "
+                                              "PCIXCC\n");
+                               else if ((service_rc == 8) && (service_rs == 770)) {
+                                       PDEBUG("Invalid key length on PCIXCC\n");
+                                       unset_ext_bitlens();
+                                       return REC_USE_PCICA;
+                               }
+                               else if ((service_rc == 8) && (service_rs == 783)) {
+                                       PDEBUG("Extended bitlengths not enabled"
+                                              "on PCIXCC\n");
+                                       unset_ext_bitlens();
+                                       return REC_USE_PCICA;
+                               }
                                else
-                                       PRINTK("service rc/rs: %d/%d\n",
+                                       PRINTK("service rc/rs (PCIXCC): %d/%d\n",
                                               service_rc, service_rs);
-                               rv = 8;
+                               return REC_OPERAND_INV;
                        }
                        src_p = (unsigned char *)
                                cprbx_p + sizeof(struct CPRBX);
@@ -2139,23 +2469,33 @@ convert_response(unsigned char *response, unsigned char *buffer,
                }
                break;
        default:
-               break;
+               src_p = (unsigned char *)errh_p;
+               PRINTK("Unrecognized Message Header: "
+                      "%02x%02x%02x%02x%02x%02x%02x%02x\n",
+                      src_p[0], src_p[1], src_p[2], src_p[3],
+                      src_p[4], src_p[5], src_p[6], src_p[7]);
+               return REC_BAD_MESSAGE;
        }
 
-       if (rv == 8)
-               return 8;
-       if (rv == 4)
+       if (reply_code)
                switch (reply_code) {
-               case REPLY_ERROR_OPERAND_INVALID:
+               case REP82_ERROR_OPERAND_INVALID:
+               case REP88_ERROR_MESSAGE_MALFORMD:
                        return REC_OPERAND_INV;
-               case REPLY_ERROR_OPERAND_SIZE:
+               case REP82_ERROR_OPERAND_SIZE:
                        return REC_OPERAND_SIZE;
-               case REPLY_ERROR_EVEN_MOD_IN_OPND:
+               case REP82_ERROR_EVEN_MOD_IN_OPND:
                        return REC_EVEN_MOD;
-               case REPLY_ERROR_MESSAGE_TYPE:
+               case REP82_ERROR_MESSAGE_TYPE:
                        return WRONG_DEVICE_TYPE;
+               case REP82_ERROR_TRANSPORT_FAIL:
+                       PRINTKW("Transport failed (APFS = %02X%02X%02X%02X)\n",
+                               t86m_p->apfs[0], t86m_p->apfs[1],
+                               t86m_p->apfs[2], t86m_p->apfs[3]);
+                       return REC_HARDWAR_ERR;
                default:
-                       return 12;
+                       PRINTKW("reply code = %d\n", reply_code);
+                       return REC_HARDWAR_ERR;
                }
 
        if (service_rc != 0)
@@ -2169,16 +2509,15 @@ convert_response(unsigned char *response, unsigned char *buffer,
        PDEBUG("Length returned = %d\n", src_l);
        tgt_p = resp_buff + icaMsg_p->outputdatalength - src_l;
        memcpy(tgt_p, src_p, src_l);
-       if ((t82h_p->type == TYPE86_RSP_CODE) && (resp_buff < tgt_p)) {
+       if ((errh_p->type == TYPE86_RSP_CODE) && (resp_buff < tgt_p)) {
                memset(resp_buff, 0, icaMsg_p->outputdatalength - src_l);
-               rv = pad_msg(resp_buff, icaMsg_p->outputdatalength, src_l);
-               if (rv != 0)
-                       return rv;
+               if (pad_msg(resp_buff, icaMsg_p->outputdatalength, src_l))
+                       return REC_INVALID_PAD;
        }
        *respbufflen_p = icaMsg_p->outputdatalength;
        if (*respbufflen_p == 0)
                PRINTK("Zero *respbufflen_p\n");
 
-       return rv;
+       return 0;
 }