2 * linux/drivers/s390/crypto/zcrypt_pcixcc.c
6 * Copyright (C) 2001, 2006 IBM Corporation
7 * Author(s): Robert Burroughs
8 * Eric Rossman (edrossma@us.ibm.com)
10 * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
11 * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com>
12 * Ralph Wuerthner <rwuerthn@de.ibm.com>
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #include <linux/module.h>
30 #include <linux/init.h>
31 #include <linux/err.h>
32 #include <linux/delay.h>
33 #include <asm/atomic.h>
34 #include <asm/uaccess.h>
37 #include "zcrypt_api.h"
38 #include "zcrypt_error.h"
39 #include "zcrypt_pcicc.h"
40 #include "zcrypt_pcixcc.h"
41 #include "zcrypt_cca_key.h"
43 #define PCIXCC_MIN_MOD_SIZE 16 /* 128 bits */
44 #define PCIXCC_MIN_MOD_SIZE_OLD 64 /* 512 bits */
45 #define PCIXCC_MAX_MOD_SIZE 256 /* 2048 bits */
47 #define PCIXCC_MCL2_SPEED_RATING 7870 /* FIXME: needs finetuning */
48 #define PCIXCC_MCL3_SPEED_RATING 7870
49 #define CEX2C_SPEED_RATING 8540
51 #define PCIXCC_MAX_ICA_MESSAGE_SIZE 0x77c /* max size type6 v2 crt message */
52 #define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply */
54 #define PCIXCC_MAX_XCRB_MESSAGE_SIZE (12*1024)
55 #define PCIXCC_MAX_XCRB_RESPONSE_SIZE PCIXCC_MAX_XCRB_MESSAGE_SIZE
56 #define PCIXCC_MAX_XCRB_DATA_SIZE (11*1024)
57 #define PCIXCC_MAX_XCRB_REPLY_SIZE (5*1024)
59 #define PCIXCC_MAX_RESPONSE_SIZE PCIXCC_MAX_XCRB_RESPONSE_SIZE
61 #define PCIXCC_CLEANUP_TIME (15*HZ)
63 static struct ap_device_id zcrypt_pcixcc_ids[] = {
64 { AP_DEVICE(AP_DEVICE_TYPE_PCIXCC) },
65 { AP_DEVICE(AP_DEVICE_TYPE_CEX2C) },
66 { /* end of list */ },
69 #ifndef CONFIG_ZCRYPT_MONOLITHIC
70 MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_ids);
71 MODULE_AUTHOR("IBM Corporation");
72 MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, "
73 "Copyright 2001, 2006 IBM Corporation");
74 MODULE_LICENSE("GPL");
77 static int zcrypt_pcixcc_probe(struct ap_device *ap_dev);
78 static void zcrypt_pcixcc_remove(struct ap_device *ap_dev);
79 static void zcrypt_pcixcc_receive(struct ap_device *, struct ap_message *,
82 static struct ap_driver zcrypt_pcixcc_driver = {
83 .probe = zcrypt_pcixcc_probe,
84 .remove = zcrypt_pcixcc_remove,
85 .receive = zcrypt_pcixcc_receive,
86 .ids = zcrypt_pcixcc_ids,
90 * The following is used to initialize the CPRBX passed to the PCIXCC/CEX2C
91 * card in a type6 message. The 3 fields that must be filled in at execution
92 * time are req_parml, rpl_parml and usage_domain.
93 * Everything about this interface is ascii/big-endian, since the
94 * device does *not* have 'Intel inside'.
96 * The CPRBX is followed immediately by the parm block.
97 * The parm block contains:
98 * - function code ('PD' 0x5044 or 'PK' 0x504B)
99 * - rule block (one of:)
100 * + 0x000A 'PKCS-1.2' (MCL2 'PD')
101 * + 0x000A 'ZERO-PAD' (MCL2 'PK')
102 * + 0x000A 'ZERO-PAD' (MCL3 'PD' or CEX2C 'PD')
103 * + 0x000A 'MRP ' (MCL3 'PK' or CEX2C 'PK')
106 static struct CPRBX static_cprbx = {
109 .func_id = {0x54,0x32},
113 * Convert a ICAMEX message to a type6 MEX message.
115 * @zdev: crypto device pointer
116 * @ap_msg: pointer to AP message
117 * @mex: pointer to user input data
119 * Returns 0 on success or -EFAULT.
121 static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_device *zdev,
122 struct ap_message *ap_msg,
123 struct ica_rsa_modexpo *mex)
125 static struct type6_hdr static_type6_hdrX = {
127 .offset1 = 0x00000058,
128 .agent_id = {'C','A',},
129 .function_code = {'P','K'},
131 static struct function_and_rules_block static_pke_fnr = {
132 .function_code = {'P','K'},
134 .only_rule = {'M','R','P',' ',' ',' ',' ',' '}
136 static struct function_and_rules_block static_pke_fnr_MCL2 = {
137 .function_code = {'P','K'},
139 .only_rule = {'Z','E','R','O','-','P','A','D'}
142 struct type6_hdr hdr;
144 struct function_and_rules_block fr;
145 unsigned short length;
147 } __attribute__((packed)) *msg = ap_msg->message;
151 msg->length = mex->inputdatalength + 2;
152 if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength))
155 /* Set up key which is located after the variable length text. */
156 size = zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength, 1);
159 size += sizeof(*msg) + mex->inputdatalength;
161 /* message header, cprbx and f&r */
162 msg->hdr = static_type6_hdrX;
163 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
164 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
166 msg->cprbx = static_cprbx;
167 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
168 msg->cprbx.rpl_msgbl = msg->hdr.FromCardLen1;
170 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
171 static_pke_fnr_MCL2 : static_pke_fnr;
173 msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx);
175 ap_msg->length = size;
180 * Convert a ICACRT message to a type6 CRT message.
182 * @zdev: crypto device pointer
183 * @ap_msg: pointer to AP message
184 * @crt: pointer to user input data
186 * Returns 0 on success or -EFAULT.
188 static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev,
189 struct ap_message *ap_msg,
190 struct ica_rsa_modexpo_crt *crt)
192 static struct type6_hdr static_type6_hdrX = {
194 .offset1 = 0x00000058,
195 .agent_id = {'C','A',},
196 .function_code = {'P','D'},
198 static struct function_and_rules_block static_pkd_fnr = {
199 .function_code = {'P','D'},
201 .only_rule = {'Z','E','R','O','-','P','A','D'}
204 static struct function_and_rules_block static_pkd_fnr_MCL2 = {
205 .function_code = {'P','D'},
207 .only_rule = {'P','K','C','S','-','1','.','2'}
210 struct type6_hdr hdr;
212 struct function_and_rules_block fr;
213 unsigned short length;
215 } __attribute__((packed)) *msg = ap_msg->message;
219 msg->length = crt->inputdatalength + 2;
220 if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength))
223 /* Set up key which is located after the variable length text. */
224 size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 1);
227 size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */
229 /* message header, cprbx and f&r */
230 msg->hdr = static_type6_hdrX;
231 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
232 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
234 msg->cprbx = static_cprbx;
235 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
236 msg->cprbx.req_parml = msg->cprbx.rpl_msgbl =
237 size - sizeof(msg->hdr) - sizeof(msg->cprbx);
239 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
240 static_pkd_fnr_MCL2 : static_pkd_fnr;
242 ap_msg->length = size;
247 * Copy results from a type 86 ICA reply message back to user space.
249 * @zdev: crypto device pointer
250 * @reply: reply AP message.
251 * @data: pointer to user output data
252 * @length: size of user output data
254 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
256 struct type86x_reply {
257 struct type86_hdr hdr;
258 struct type86_fmt2_ext fmt2;
260 unsigned char pad[4]; /* 4 byte function code/rules block ? */
261 unsigned short length;
263 } __attribute__((packed));
265 static int convert_type86_ica(struct zcrypt_device *zdev,
266 struct ap_message *reply,
267 char __user *outputdata,
268 unsigned int outputdatalength)
270 static unsigned char static_pad[] = {
272 0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD,
273 0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57,
274 0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B,
275 0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39,
276 0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5,
277 0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D,
278 0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB,
279 0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F,
280 0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9,
281 0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45,
282 0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9,
283 0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F,
284 0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD,
285 0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D,
286 0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD,
287 0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9,
288 0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B,
289 0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B,
290 0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B,
291 0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD,
292 0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7,
293 0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1,
294 0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3,
295 0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23,
296 0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55,
297 0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43,
298 0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F,
299 0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F,
300 0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5,
301 0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD,
302 0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41,
303 0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09
305 struct type86x_reply *msg = reply->message;
306 unsigned short service_rc, service_rs;
307 unsigned int reply_len, pad_len;
310 service_rc = msg->cprbx.ccp_rtcode;
311 if (unlikely(service_rc != 0)) {
312 service_rs = msg->cprbx.ccp_rscode;
313 if (service_rc == 8 && service_rs == 66) {
314 PDEBUG("Bad block format on PCIXCC/CEX2C\n");
317 if (service_rc == 8 && service_rs == 65) {
318 PDEBUG("Probably an even modulus on PCIXCC/CEX2C\n");
321 if (service_rc == 8 && service_rs == 770) {
322 PDEBUG("Invalid key length on PCIXCC/CEX2C\n");
323 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
326 if (service_rc == 8 && service_rs == 783) {
327 PDEBUG("Extended bitlengths not enabled on PCIXCC/CEX2C\n");
328 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
331 PRINTK("Unknown service rc/rs (PCIXCC/CEX2C): %d/%d\n",
332 service_rc, service_rs);
334 return -EAGAIN; /* repeat the request on a different device. */
337 reply_len = msg->length - 2;
338 if (reply_len > outputdatalength)
341 * For all encipher requests, the length of the ciphertext (reply_len)
342 * will always equal the modulus length. For MEX decipher requests
343 * the output needs to get padded. Minimum pad size is 10.
345 * Currently, the cases where padding will be added is for:
346 * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support
347 * ZERO-PAD and CRT is only supported for PKD requests)
350 pad_len = outputdatalength - reply_len;
354 /* 'restore' padding left in the PCICC/PCIXCC card. */
355 if (copy_to_user(outputdata, static_pad, pad_len - 1))
357 if (put_user(0, outputdata + pad_len - 1))
360 /* Copy the crypto response to user space. */
361 if (copy_to_user(outputdata + pad_len, data, reply_len))
366 static int convert_response_ica(struct zcrypt_device *zdev,
367 struct ap_message *reply,
368 char __user *outputdata,
369 unsigned int outputdatalength)
371 struct type86x_reply *msg = reply->message;
373 /* Response type byte is the second byte in the response. */
374 switch (((unsigned char *) reply->message)[1]) {
375 case TYPE82_RSP_CODE:
376 case TYPE88_RSP_CODE:
377 return convert_error(zdev, reply);
378 case TYPE86_RSP_CODE:
379 if (msg->hdr.reply_code)
380 return convert_error(zdev, reply);
381 if (msg->cprbx.cprb_ver_id == 0x02)
382 return convert_type86_ica(zdev, reply,
383 outputdata, outputdatalength);
384 /* no break, incorrect cprb version is an unknown response */
385 default: /* Unknown response type, this should NEVER EVER happen */
386 PRINTK("Unrecognized Message Header: %08x%08x\n",
387 *(unsigned int *) reply->message,
388 *(unsigned int *) (reply->message+4));
390 return -EAGAIN; /* repeat the request on a different device. */
395 * This function is called from the AP bus code after a crypto request
396 * "msg" has finished with the reply message "reply".
397 * It is called from tasklet context.
398 * @ap_dev: pointer to the AP device
399 * @msg: pointer to the AP message
400 * @reply: pointer to the AP reply message
402 static void zcrypt_pcixcc_receive(struct ap_device *ap_dev,
403 struct ap_message *msg,
404 struct ap_message *reply)
406 static struct error_hdr error_reply = {
407 .type = TYPE82_RSP_CODE,
408 .reply_code = REP82_ERROR_MACHINE_FAILURE,
410 struct type86x_reply *t86r = reply->message;
413 /* Copy the reply message to the request message buffer. */
415 memcpy(msg->message, &error_reply, sizeof(error_reply));
416 else if (t86r->hdr.type == TYPE86_RSP_CODE &&
417 t86r->cprbx.cprb_ver_id == 0x02) {
418 length = sizeof(struct type86x_reply) + t86r->length - 2;
419 length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length);
420 memcpy(msg->message, reply->message, length);
422 memcpy(msg->message, reply->message, sizeof error_reply);
423 complete((struct completion *) msg->private);
426 static atomic_t zcrypt_step = ATOMIC_INIT(0);
429 * The request distributor calls this function if it picked the PCIXCC/CEX2C
430 * device to handle a modexpo request.
431 * @zdev: pointer to zcrypt_device structure that identifies the
432 * PCIXCC/CEX2C device to the request distributor
433 * @mex: pointer to the modexpo request buffer
435 static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
436 struct ica_rsa_modexpo *mex)
438 struct ap_message ap_msg;
439 struct completion work;
442 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
445 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
446 atomic_inc_return(&zcrypt_step);
447 ap_msg.private = &work;
448 rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex);
451 init_completion(&work);
452 ap_queue_message(zdev->ap_dev, &ap_msg);
453 rc = wait_for_completion_interruptible_timeout(
454 &work, PCIXCC_CLEANUP_TIME);
456 rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
457 mex->outputdatalength);
459 /* Signal pending or message timed out. */
460 ap_cancel_message(zdev->ap_dev, &ap_msg);
462 /* Message timed out. */
466 free_page((unsigned long) ap_msg.message);
471 * The request distributor calls this function if it picked the PCIXCC/CEX2C
472 * device to handle a modexpo_crt request.
473 * @zdev: pointer to zcrypt_device structure that identifies the
474 * PCIXCC/CEX2C device to the request distributor
475 * @crt: pointer to the modexpoc_crt request buffer
477 static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
478 struct ica_rsa_modexpo_crt *crt)
480 struct ap_message ap_msg;
481 struct completion work;
484 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
487 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
488 atomic_inc_return(&zcrypt_step);
489 ap_msg.private = &work;
490 rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt);
493 init_completion(&work);
494 ap_queue_message(zdev->ap_dev, &ap_msg);
495 rc = wait_for_completion_interruptible_timeout(
496 &work, PCIXCC_CLEANUP_TIME);
498 rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
499 crt->outputdatalength);
501 /* Signal pending or message timed out. */
502 ap_cancel_message(zdev->ap_dev, &ap_msg);
504 /* Message timed out. */
508 free_page((unsigned long) ap_msg.message);
513 * The crypto operations for a PCIXCC/CEX2C card.
515 static struct zcrypt_ops zcrypt_pcixcc_ops = {
516 .rsa_modexpo = zcrypt_pcixcc_modexpo,
517 .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
521 * Micro-code detection function. Its sends a message to a pcixcc card
522 * to find out the microcode level.
523 * @ap_dev: pointer to the AP device.
525 static int zcrypt_pcixcc_mcl(struct ap_device *ap_dev)
527 static unsigned char msg[] = {
528 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
529 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
530 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
531 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
532 0x43,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
533 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
534 0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x00,
535 0x00,0x00,0x01,0xC4,0x00,0x00,0x00,0x00,
536 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
537 0x00,0x00,0x07,0x24,0x00,0x00,0x00,0x00,
538 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
539 0x00,0xDC,0x02,0x00,0x00,0x00,0x54,0x32,
540 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE8,
541 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x24,
542 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
543 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
544 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
545 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
546 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
547 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
548 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
549 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
550 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
551 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
552 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
553 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
554 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
555 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
556 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
557 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
558 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
559 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
560 0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
561 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
562 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
563 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
564 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
565 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
566 0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x0A,
567 0x4D,0x52,0x50,0x20,0x20,0x20,0x20,0x20,
568 0x00,0x42,0x00,0x01,0x02,0x03,0x04,0x05,
569 0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
570 0x0E,0x0F,0x00,0x11,0x22,0x33,0x44,0x55,
571 0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,
572 0xEE,0xFF,0xFF,0xEE,0xDD,0xCC,0xBB,0xAA,
573 0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,
574 0x11,0x00,0x01,0x23,0x45,0x67,0x89,0xAB,
575 0xCD,0xEF,0xFE,0xDC,0xBA,0x98,0x76,0x54,
576 0x32,0x10,0x00,0x9A,0x00,0x98,0x00,0x00,
577 0x1E,0x00,0x00,0x94,0x00,0x00,0x00,0x00,
578 0x04,0x00,0x00,0x8C,0x00,0x00,0x00,0x40,
579 0x02,0x00,0x00,0x40,0xBA,0xE8,0x23,0x3C,
580 0x75,0xF3,0x91,0x61,0xD6,0x73,0x39,0xCF,
581 0x7B,0x6D,0x8E,0x61,0x97,0x63,0x9E,0xD9,
582 0x60,0x55,0xD6,0xC7,0xEF,0xF8,0x1E,0x63,
583 0x95,0x17,0xCC,0x28,0x45,0x60,0x11,0xC5,
584 0xC4,0x4E,0x66,0xC6,0xE6,0xC3,0xDE,0x8A,
585 0x19,0x30,0xCF,0x0E,0xD7,0xAA,0xDB,0x01,
586 0xD8,0x00,0xBB,0x8F,0x39,0x9F,0x64,0x28,
587 0xF5,0x7A,0x77,0x49,0xCC,0x6B,0xA3,0x91,
588 0x97,0x70,0xE7,0x60,0x1E,0x39,0xE1,0xE5,
589 0x33,0xE1,0x15,0x63,0x69,0x08,0x80,0x4C,
590 0x67,0xC4,0x41,0x8F,0x48,0xDF,0x26,0x98,
591 0xF1,0xD5,0x8D,0x88,0xD9,0x6A,0xA4,0x96,
592 0xC5,0x84,0xD9,0x30,0x49,0x67,0x7D,0x19,
593 0xB1,0xB3,0x45,0x4D,0xB2,0x53,0x9A,0x47,
594 0x3C,0x7C,0x55,0xBF,0xCC,0x85,0x00,0x36,
597 unsigned long long psmid;
602 reply = (void *) get_zeroed_page(GFP_KERNEL);
606 rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, msg, sizeof(msg));
610 /* Wait for the test message to complete. */
611 for (i = 0; i < 6; i++) {
613 rc = ap_recv(ap_dev->qid, &psmid, reply, 4096);
614 if (rc == 0 && psmid == 0x0102030405060708ULL)
624 cprbx = (struct CPRBX *) (reply + 48);
625 if (cprbx->ccp_rtcode == 8 && cprbx->ccp_rscode == 33)
626 rc = ZCRYPT_PCIXCC_MCL2;
628 rc = ZCRYPT_PCIXCC_MCL3;
630 free_page((unsigned long) reply);
635 * Probe function for PCIXCC/CEX2C cards. It always accepts the AP device
636 * since the bus_match already checked the hardware type. The PCIXCC
637 * cards come in two flavours: micro code level 2 and micro code level 3.
638 * This is checked by sending a test message to the device.
639 * @ap_dev: pointer to the AP device.
641 static int zcrypt_pcixcc_probe(struct ap_device *ap_dev)
643 struct zcrypt_device *zdev;
646 zdev = zcrypt_device_alloc(PCIXCC_MAX_RESPONSE_SIZE);
649 zdev->ap_dev = ap_dev;
650 zdev->ops = &zcrypt_pcixcc_ops;
652 if (ap_dev->device_type == AP_DEVICE_TYPE_PCIXCC) {
653 rc = zcrypt_pcixcc_mcl(ap_dev);
655 zcrypt_device_free(zdev);
658 zdev->user_space_type = rc;
659 if (rc == ZCRYPT_PCIXCC_MCL2) {
660 zdev->type_string = "PCIXCC_MCL2";
661 zdev->speed_rating = PCIXCC_MCL2_SPEED_RATING;
662 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
663 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
665 zdev->type_string = "PCIXCC_MCL3";
666 zdev->speed_rating = PCIXCC_MCL3_SPEED_RATING;
667 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
668 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
671 zdev->user_space_type = ZCRYPT_CEX2C;
672 zdev->type_string = "CEX2C";
673 zdev->speed_rating = CEX2C_SPEED_RATING;
674 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
675 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
677 ap_dev->reply = &zdev->reply;
678 ap_dev->private = zdev;
679 rc = zcrypt_device_register(zdev);
685 ap_dev->private = NULL;
686 zcrypt_device_free(zdev);
691 * This is called to remove the extended PCIXCC/CEX2C driver information
692 * if an AP device is removed.
694 static void zcrypt_pcixcc_remove(struct ap_device *ap_dev)
696 struct zcrypt_device *zdev = ap_dev->private;
698 zcrypt_device_unregister(zdev);
701 int __init zcrypt_pcixcc_init(void)
703 return ap_driver_register(&zcrypt_pcixcc_driver, THIS_MODULE, "pcixcc");
706 void zcrypt_pcixcc_exit(void)
708 ap_driver_unregister(&zcrypt_pcixcc_driver);
711 #ifndef CONFIG_ZCRYPT_MONOLITHIC
712 module_init(zcrypt_pcixcc_init);
713 module_exit(zcrypt_pcixcc_exit);