Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / s390 / crypto / z90hardware.c
index beb6a5e..be60795 100644 (file)
@@ -1,9 +1,9 @@
 /*
  *  linux/drivers/s390/crypto/z90hardware.c
  *
- *  z90crypt 1.3.2
+ *  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)
  *
 #include "z90crypt.h"
 #include "z90common.h"
 
-#define VERSION_Z90HARDWARE_C "$Revision: 1.33 $"
-
-char z90hardware_version[] __initdata =
-       "z90hardware.o (" VERSION_Z90HARDWARE_C "/"
-                         VERSION_Z90COMMON_H "/" VERSION_Z90CRYPT_H ")";
-
 struct cca_token_hdr {
        unsigned char  token_identifier;
        unsigned char  version;
@@ -283,48 +277,6 @@ struct type6_msg {
        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_FIELDO  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_RESERVED_FIELD   0x88
-#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;
@@ -338,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;
@@ -538,6 +490,8 @@ static struct function_and_rules_block static_pke_function_and_rulesX = {
        {'M','R','P',' ',' ',' ',' ',' '}
 };
 
+static unsigned char static_PKE_function_code[2] = {0x50, 0x4B};
+
 struct T6_keyBlock_hdrX {
        unsigned short blen;
        unsigned short ulen;
@@ -688,9 +642,136 @@ static struct cca_public_sec static_cca_pub_sec = {
 #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)
@@ -698,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"
@@ -768,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"
@@ -834,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"
@@ -913,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"
@@ -1040,10 +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:
-                               stat = HD_NOT_THERE;
-                               *dev_type = NILDEV;
-                               break;
                        case PCICA_HW:
                                *dev_type = PCICA;
                                break;
@@ -1056,6 +1133,9 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type)
                        case CEX2C_HW:
                                *dev_type = CEX2C;
                                break;
+                       case CEX2A_HW:
+                               *dev_type = CEX2A;
+                               break;
                        default:
                                *dev_type = NILDEV;
                                break;
@@ -1212,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]);
@@ -2040,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 = ((long_len <= 64) ? 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)
@@ -2082,6 +2333,16 @@ convert_request(unsigned char *buffer, int func, unsigned short function,
                                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;
 }
@@ -2092,8 +2353,8 @@ unset_ext_bitlens(void)
 {
        if (!ext_bitlens_msg_count) {
                PRINTK("Unable to use coprocessors for extended bitlengths. "
-                      "Using PCICAs (if present) for extended bitlengths. "
-                      "This is not an error.\n");
+                      "Using PCICAs/CEX2As (if present) for extended "
+                      "bitlengths. This is not an error.\n");
                ext_bitlens_msg_count++;
        }
        ext_bitlens = 0;
@@ -2104,7 +2365,8 @@ 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_fmt2_msg *t86m_p =  (struct type86_fmt2_msg *) response;
        int reply_code, service_rc, service_rs, src_l;
@@ -2117,21 +2379,27 @@ convert_response(unsigned char *response, unsigned char *buffer,
        service_rc = 0;
        service_rs = 0;
        src_l = 0;
-       switch (t82h_p->type) {
+       switch (errh_p->type) {
        case TYPE82_RSP_CODE:
-               reply_code = t82h_p->reply_code;
-               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 = t86m_p->hdr.reply_code;
+               reply_code = t86m_p->header.reply_code;
                if (reply_code != 0)
                        break;
                cprb_p = (struct CPRB *)
@@ -2143,6 +2411,9 @@ convert_response(unsigned char *response, unsigned char *buffer,
                                le2toI(cprb_p->ccp_rscode, &service_rs);
                                if ((service_rc == 8) && (service_rs == 66))
                                        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();
@@ -2155,7 +2426,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
                                        return REC_USE_PCICA;
                                }
                                else
-                                       PRINTK("service rc/rs: %d/%d\n",
+                                       PRINTK("service rc/rs (PCICC): %d/%d\n",
                                               service_rc, service_rs);
                                return REC_OPERAND_INV;
                        }
@@ -2169,7 +2440,10 @@ 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("Bad block format on PCXICC\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();
@@ -2182,7 +2456,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
                                        return REC_USE_PCICA;
                                }
                                else
-                                       PRINTK("service rc/rs: %d/%d\n",
+                                       PRINTK("service rc/rs (PCIXCC): %d/%d\n",
                                               service_rc, service_rs);
                                return REC_OPERAND_INV;
                        }
@@ -2195,20 +2469,34 @@ convert_response(unsigned char *response, unsigned char *buffer,
                }
                break;
        default:
+               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 (reply_code)
                switch (reply_code) {
-               case REPLY_ERROR_OPERAND_INVALID:
+               case REP82_ERROR_MACHINE_FAILURE:
+                       if (errh_p->type == TYPE82_RSP_CODE)
+                               PRINTKW("Machine check failure\n");
+                       else
+                               PRINTKW("Module failure\n");
+                       return REC_HARDWAR_ERR;
+               case REP82_ERROR_OPERAND_INVALID:
+                       return REC_OPERAND_INV;
+               case REP88_ERROR_MESSAGE_MALFORMD:
+                       PRINTKW("Message malformed\n");
                        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 REPLY_ERROR_TRANSPORT_FAIL:
+               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]);
@@ -2229,7 +2517,7 @@ 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);
                if (pad_msg(resp_buff, icaMsg_p->outputdatalength, src_l))
                        return REC_INVALID_PAD;