brintos

brintos / linux-shallow public Read only

0
0
Text · 43.9 KiB · 0d484fe Raw
1702 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 *    tape device discipline for 3590 tapes.4 *5 *    Copyright IBM Corp. 2001, 20096 *    Author(s): Stefan Bader <shbader@de.ibm.com>7 *		 Michael Holzheu <holzheu@de.ibm.com>8 *		 Martin Schwidefsky <schwidefsky@de.ibm.com>9 */10 11#define KMSG_COMPONENT "tape_3590"12#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt13 14#include <linux/module.h>15#include <linux/slab.h>16#include <linux/init.h>17#include <linux/bio.h>18#include <asm/ebcdic.h>19 20#define TAPE_DBF_AREA	tape_3590_dbf21#define BUFSIZE 512	/* size of buffers for dynamic generated messages */22 23#include "tape.h"24#include "tape_std.h"25#include "tape_3590.h"26 27static struct workqueue_struct *tape_3590_wq;28 29/*30 * Pointer to debug area.31 */32debug_info_t *TAPE_DBF_AREA = NULL;33EXPORT_SYMBOL(TAPE_DBF_AREA);34 35/*******************************************************************36 * Error Recovery functions:37 * - Read Opposite:		 implemented38 * - Read Device (buffered) log: BRA39 * - Read Library log:		 BRA40 * - Swap Devices:		 BRA41 * - Long Busy:			 implemented42 * - Special Intercept:		 BRA43 * - Read Alternate:		 implemented44 *******************************************************************/45 46static const char *tape_3590_msg[TAPE_3590_MAX_MSG] = {47	[0x00] = "",48	[0x10] = "Lost Sense",49	[0x11] = "Assigned Elsewhere",50	[0x12] = "Allegiance Reset",51	[0x13] = "Shared Access Violation",52	[0x20] = "Command Reject",53	[0x21] = "Configuration Error",54	[0x22] = "Protection Exception",55	[0x23] = "Write Protect",56	[0x24] = "Write Length",57	[0x25] = "Read-Only Format",58	[0x31] = "Beginning of Partition",59	[0x33] = "End of Partition",60	[0x34] = "End of Data",61	[0x35] = "Block not found",62	[0x40] = "Device Intervention",63	[0x41] = "Loader Intervention",64	[0x42] = "Library Intervention",65	[0x50] = "Write Error",66	[0x51] = "Erase Error",67	[0x52] = "Formatting Error",68	[0x53] = "Read Error",69	[0x54] = "Unsupported Format",70	[0x55] = "No Formatting",71	[0x56] = "Positioning lost",72	[0x57] = "Read Length",73	[0x60] = "Unsupported Medium",74	[0x61] = "Medium Length Error",75	[0x62] = "Medium removed",76	[0x64] = "Load Check",77	[0x65] = "Unload Check",78	[0x70] = "Equipment Check",79	[0x71] = "Bus out Check",80	[0x72] = "Protocol Error",81	[0x73] = "Interface Error",82	[0x74] = "Overrun",83	[0x75] = "Halt Signal",84	[0x90] = "Device fenced",85	[0x91] = "Device Path fenced",86	[0xa0] = "Volume misplaced",87	[0xa1] = "Volume inaccessible",88	[0xa2] = "Volume in input",89	[0xa3] = "Volume ejected",90	[0xa4] = "All categories reserved",91	[0xa5] = "Duplicate Volume",92	[0xa6] = "Library Manager Offline",93	[0xa7] = "Library Output Station full",94	[0xa8] = "Vision System non-operational",95	[0xa9] = "Library Manager Equipment Check",96	[0xaa] = "Library Equipment Check",97	[0xab] = "All Library Cells full",98	[0xac] = "No Cleaner Volumes in Library",99	[0xad] = "I/O Station door open",100	[0xae] = "Subsystem environmental alert",101};102 103static int crypt_supported(struct tape_device *device)104{105	return TAPE390_CRYPT_SUPPORTED(TAPE_3590_CRYPT_INFO(device));106}107 108static int crypt_enabled(struct tape_device *device)109{110	return TAPE390_CRYPT_ON(TAPE_3590_CRYPT_INFO(device));111}112 113static void ext_to_int_kekl(struct tape390_kekl *in,114			    struct tape3592_kekl *out)115{116	int len;117 118	memset(out, 0, sizeof(*out));119	if (in->type == TAPE390_KEKL_TYPE_HASH)120		out->flags |= 0x40;121	if (in->type_on_tape == TAPE390_KEKL_TYPE_HASH)122		out->flags |= 0x80;123	len = min(sizeof(out->label), strlen(in->label));124	memcpy(out->label, in->label, len);125	memset(out->label + len, ' ', sizeof(out->label) - len);126	ASCEBC(out->label, sizeof(out->label));127}128 129static void int_to_ext_kekl(struct tape3592_kekl *in,130			    struct tape390_kekl *out)131{132	memset(out, 0, sizeof(*out));133	if(in->flags & 0x40)134		out->type = TAPE390_KEKL_TYPE_HASH;135	else136		out->type = TAPE390_KEKL_TYPE_LABEL;137	if(in->flags & 0x80)138		out->type_on_tape = TAPE390_KEKL_TYPE_HASH;139	else140		out->type_on_tape = TAPE390_KEKL_TYPE_LABEL;141	memcpy(out->label, in->label, sizeof(in->label));142	EBCASC(out->label, sizeof(in->label));143	strim(out->label);144}145 146static void int_to_ext_kekl_pair(struct tape3592_kekl_pair *in,147				 struct tape390_kekl_pair *out)148{149	if (in->count == 0) {150		out->kekl[0].type = TAPE390_KEKL_TYPE_NONE;151		out->kekl[0].type_on_tape = TAPE390_KEKL_TYPE_NONE;152		out->kekl[1].type = TAPE390_KEKL_TYPE_NONE;153		out->kekl[1].type_on_tape = TAPE390_KEKL_TYPE_NONE;154	} else if (in->count == 1) {155		int_to_ext_kekl(&in->kekl[0], &out->kekl[0]);156		out->kekl[1].type = TAPE390_KEKL_TYPE_NONE;157		out->kekl[1].type_on_tape = TAPE390_KEKL_TYPE_NONE;158	} else if (in->count == 2) {159		int_to_ext_kekl(&in->kekl[0], &out->kekl[0]);160		int_to_ext_kekl(&in->kekl[1], &out->kekl[1]);161	} else {162		printk("Invalid KEKL number: %d\n", in->count);163		BUG();164	}165}166 167static int check_ext_kekl(struct tape390_kekl *kekl)168{169	if (kekl->type == TAPE390_KEKL_TYPE_NONE)170		goto invalid;171	if (kekl->type > TAPE390_KEKL_TYPE_HASH)172		goto invalid;173	if (kekl->type_on_tape == TAPE390_KEKL_TYPE_NONE)174		goto invalid;175	if (kekl->type_on_tape > TAPE390_KEKL_TYPE_HASH)176		goto invalid;177	if ((kekl->type == TAPE390_KEKL_TYPE_HASH) &&178	    (kekl->type_on_tape == TAPE390_KEKL_TYPE_LABEL))179		goto invalid;180 181	return 0;182invalid:183	return -EINVAL;184}185 186static int check_ext_kekl_pair(struct tape390_kekl_pair *kekls)187{188	if (check_ext_kekl(&kekls->kekl[0]))189		goto invalid;190	if (check_ext_kekl(&kekls->kekl[1]))191		goto invalid;192 193	return 0;194invalid:195	return -EINVAL;196}197 198/*199 * Query KEKLs200 */201static int tape_3592_kekl_query(struct tape_device *device,202				struct tape390_kekl_pair *ext_kekls)203{204	struct tape_request *request;205	struct tape3592_kekl_query_order *order;206	struct tape3592_kekl_query_data *int_kekls;207	int rc;208 209	DBF_EVENT(6, "tape3592_kekl_query\n");210	int_kekls = kmalloc(sizeof(*int_kekls), GFP_KERNEL|GFP_DMA);211	if (!int_kekls)212		return -ENOMEM;213	request = tape_alloc_request(2, sizeof(*order));214	if (IS_ERR(request)) {215		rc = PTR_ERR(request);216		goto fail_malloc;217	}218	order = request->cpdata;219	memset(order,0,sizeof(*order));220	order->code = 0xe2;221	order->max_count = 2;222	request->op = TO_KEKL_QUERY;223	tape_ccw_cc(request->cpaddr, PERF_SUBSYS_FUNC, sizeof(*order), order);224	tape_ccw_end(request->cpaddr + 1, READ_SS_DATA, sizeof(*int_kekls),225		     int_kekls);226	rc = tape_do_io(device, request);227	if (rc)228		goto fail_request;229	int_to_ext_kekl_pair(&int_kekls->kekls, ext_kekls);230 231	rc = 0;232fail_request:233	tape_free_request(request);234fail_malloc:235	kfree(int_kekls);236	return rc;237}238 239/*240 * IOCTL: Query KEKLs241 */242static int tape_3592_ioctl_kekl_query(struct tape_device *device,243				      unsigned long arg)244{245	int rc;246	struct tape390_kekl_pair *ext_kekls;247 248	DBF_EVENT(6, "tape_3592_ioctl_kekl_query\n");249	if (!crypt_supported(device))250		return -ENOSYS;251	if (!crypt_enabled(device))252		return -EUNATCH;253	ext_kekls = kmalloc(sizeof(*ext_kekls), GFP_KERNEL);254	if (!ext_kekls)255		return -ENOMEM;256	rc = tape_3592_kekl_query(device, ext_kekls);257	if (rc != 0)258		goto fail;259	if (copy_to_user((char __user *) arg, ext_kekls, sizeof(*ext_kekls))) {260		rc = -EFAULT;261		goto fail;262	}263	rc = 0;264fail:265	kfree(ext_kekls);266	return rc;267}268 269static int tape_3590_mttell(struct tape_device *device, int mt_count);270 271/*272 * Set KEKLs273 */274static int tape_3592_kekl_set(struct tape_device *device,275			      struct tape390_kekl_pair *ext_kekls)276{277	struct tape_request *request;278	struct tape3592_kekl_set_order *order;279 280	DBF_EVENT(6, "tape3592_kekl_set\n");281	if (check_ext_kekl_pair(ext_kekls)) {282		DBF_EVENT(6, "invalid kekls\n");283		return -EINVAL;284	}285	if (tape_3590_mttell(device, 0) != 0)286		return -EBADSLT;287	request = tape_alloc_request(1, sizeof(*order));288	if (IS_ERR(request))289		return PTR_ERR(request);290	order = request->cpdata;291	memset(order, 0, sizeof(*order));292	order->code = 0xe3;293	order->kekls.count = 2;294	ext_to_int_kekl(&ext_kekls->kekl[0], &order->kekls.kekl[0]);295	ext_to_int_kekl(&ext_kekls->kekl[1], &order->kekls.kekl[1]);296	request->op = TO_KEKL_SET;297	tape_ccw_end(request->cpaddr, PERF_SUBSYS_FUNC, sizeof(*order), order);298 299	return tape_do_io_free(device, request);300}301 302/*303 * IOCTL: Set KEKLs304 */305static int tape_3592_ioctl_kekl_set(struct tape_device *device,306				    unsigned long arg)307{308	int rc;309	struct tape390_kekl_pair *ext_kekls;310 311	DBF_EVENT(6, "tape_3592_ioctl_kekl_set\n");312	if (!crypt_supported(device))313		return -ENOSYS;314	if (!crypt_enabled(device))315		return -EUNATCH;316	ext_kekls = memdup_user((char __user *)arg, sizeof(*ext_kekls));317	if (IS_ERR(ext_kekls))318		return PTR_ERR(ext_kekls);319	rc = tape_3592_kekl_set(device, ext_kekls);320	kfree(ext_kekls);321	return rc;322}323 324/*325 * Enable encryption326 */327static struct tape_request *__tape_3592_enable_crypt(struct tape_device *device)328{329	struct tape_request *request;330	char *data;331 332	DBF_EVENT(6, "tape_3592_enable_crypt\n");333	if (!crypt_supported(device))334		return ERR_PTR(-ENOSYS);335	request = tape_alloc_request(2, 72);336	if (IS_ERR(request))337		return request;338	data = request->cpdata;339	memset(data,0,72);340 341	data[0]       = 0x05;342	data[36 + 0]  = 0x03;343	data[36 + 1]  = 0x03;344	data[36 + 4]  = 0x40;345	data[36 + 6]  = 0x01;346	data[36 + 14] = 0x2f;347	data[36 + 18] = 0xc3;348	data[36 + 35] = 0x72;349	request->op = TO_CRYPT_ON;350	tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data);351	tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36);352	return request;353}354 355static int tape_3592_enable_crypt(struct tape_device *device)356{357	struct tape_request *request;358 359	request = __tape_3592_enable_crypt(device);360	if (IS_ERR(request))361		return PTR_ERR(request);362	return tape_do_io_free(device, request);363}364 365static void tape_3592_enable_crypt_async(struct tape_device *device)366{367	struct tape_request *request;368 369	request = __tape_3592_enable_crypt(device);370	if (!IS_ERR(request))371		tape_do_io_async_free(device, request);372}373 374/*375 * Disable encryption376 */377static struct tape_request *__tape_3592_disable_crypt(struct tape_device *device)378{379	struct tape_request *request;380	char *data;381 382	DBF_EVENT(6, "tape_3592_disable_crypt\n");383	if (!crypt_supported(device))384		return ERR_PTR(-ENOSYS);385	request = tape_alloc_request(2, 72);386	if (IS_ERR(request))387		return request;388	data = request->cpdata;389	memset(data,0,72);390 391	data[0]       = 0x05;392	data[36 + 0]  = 0x03;393	data[36 + 1]  = 0x03;394	data[36 + 35] = 0x32;395 396	request->op = TO_CRYPT_OFF;397	tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data);398	tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36);399 400	return request;401}402 403static int tape_3592_disable_crypt(struct tape_device *device)404{405	struct tape_request *request;406 407	request = __tape_3592_disable_crypt(device);408	if (IS_ERR(request))409		return PTR_ERR(request);410	return tape_do_io_free(device, request);411}412 413static void tape_3592_disable_crypt_async(struct tape_device *device)414{415	struct tape_request *request;416 417	request = __tape_3592_disable_crypt(device);418	if (!IS_ERR(request))419		tape_do_io_async_free(device, request);420}421 422/*423 * IOCTL: Set encryption status424 */425static int tape_3592_ioctl_crypt_set(struct tape_device *device,426				     unsigned long arg)427{428	struct tape390_crypt_info info;429 430	DBF_EVENT(6, "tape_3592_ioctl_crypt_set\n");431	if (!crypt_supported(device))432		return -ENOSYS;433	if (copy_from_user(&info, (char __user *)arg, sizeof(info)))434		return -EFAULT;435	if (info.status & ~TAPE390_CRYPT_ON_MASK)436		return -EINVAL;437	if (info.status & TAPE390_CRYPT_ON_MASK)438		return tape_3592_enable_crypt(device);439	else440		return tape_3592_disable_crypt(device);441}442 443static int tape_3590_sense_medium(struct tape_device *device);444 445/*446 * IOCTL: Query enryption status447 */448static int tape_3592_ioctl_crypt_query(struct tape_device *device,449				       unsigned long arg)450{451	DBF_EVENT(6, "tape_3592_ioctl_crypt_query\n");452	if (!crypt_supported(device))453		return -ENOSYS;454	tape_3590_sense_medium(device);455	if (copy_to_user((char __user *) arg, &TAPE_3590_CRYPT_INFO(device),456		sizeof(TAPE_3590_CRYPT_INFO(device))))457		return -EFAULT;458	else459		return 0;460}461 462/*463 * 3590 IOCTL Overload464 */465static int466tape_3590_ioctl(struct tape_device *device, unsigned int cmd, unsigned long arg)467{468	switch (cmd) {469	case TAPE390_DISPLAY: {470		struct display_struct disp;471 472		if (copy_from_user(&disp, (char __user *) arg, sizeof(disp)))473			return -EFAULT;474 475		return tape_std_display(device, &disp);476	}477	case TAPE390_KEKL_SET:478		return tape_3592_ioctl_kekl_set(device, arg);479	case TAPE390_KEKL_QUERY:480		return tape_3592_ioctl_kekl_query(device, arg);481	case TAPE390_CRYPT_SET:482		return tape_3592_ioctl_crypt_set(device, arg);483	case TAPE390_CRYPT_QUERY:484		return tape_3592_ioctl_crypt_query(device, arg);485	default:486		return -EINVAL;	/* no additional ioctls */487	}488}489 490/*491 * SENSE Medium: Get Sense data about medium state492 */493static int tape_3590_sense_medium(struct tape_device *device)494{495	struct tape_request *request;496 497	request = tape_alloc_request(1, 128);498	if (IS_ERR(request))499		return PTR_ERR(request);500	request->op = TO_MSEN;501	tape_ccw_end(request->cpaddr, MEDIUM_SENSE, 128, request->cpdata);502	return tape_do_io_free(device, request);503}504 505static void tape_3590_sense_medium_async(struct tape_device *device)506{507	struct tape_request *request;508 509	request = tape_alloc_request(1, 128);510	if (IS_ERR(request))511		return;512	request->op = TO_MSEN;513	tape_ccw_end(request->cpaddr, MEDIUM_SENSE, 128, request->cpdata);514	tape_do_io_async_free(device, request);515}516 517/*518 * MTTELL: Tell block. Return the number of block relative to current file.519 */520static int521tape_3590_mttell(struct tape_device *device, int mt_count)522{523	__u64 block_id;524	int rc;525 526	rc = tape_std_read_block_id(device, &block_id);527	if (rc)528		return rc;529	return block_id >> 32;530}531 532/*533 * MTSEEK: seek to the specified block.534 */535static int536tape_3590_mtseek(struct tape_device *device, int count)537{538	struct tape_request *request;539 540	DBF_EVENT(6, "xsee id: %x\n", count);541	request = tape_alloc_request(3, 4);542	if (IS_ERR(request))543		return PTR_ERR(request);544	request->op = TO_LBL;545	tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);546	*(__u32 *) request->cpdata = count;547	tape_ccw_cc(request->cpaddr + 1, LOCATE, 4, request->cpdata);548	tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL);549	return tape_do_io_free(device, request);550}551 552/*553 * Read Opposite Error Recovery Function:554 * Used, when Read Forward does not work555 */556static void557tape_3590_read_opposite(struct tape_device *device,558			struct tape_request *request)559{560	struct tape_3590_disc_data *data;561 562	/*563	 * We have allocated 4 ccws in tape_std_read, so we can now564	 * transform the request to a read backward, followed by a565	 * forward space block.566	 */567	request->op = TO_RBA;568	tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);569	data = device->discdata;570	tape_ccw_cc_idal(request->cpaddr + 1, data->read_back_op,571			 device->char_data.idal_buf);572	tape_ccw_cc(request->cpaddr + 2, FORSPACEBLOCK, 0, NULL);573	tape_ccw_end(request->cpaddr + 3, NOP, 0, NULL);574	DBF_EVENT(6, "xrop ccwg\n");575}576 577/*578 * Read Attention Msg579 * This should be done after an interrupt with attention bit (0x80)580 * in device state.581 *582 * After a "read attention message" request there are two possible583 * results:584 *585 * 1. A unit check is presented, when attention sense is present (e.g. when586 * a medium has been unloaded). The attention sense comes then587 * together with the unit check. The recovery action is either "retry"588 * (in case there is an attention message pending) or "permanent error".589 *590 * 2. The attention msg is written to the "read subsystem data" buffer.591 * In this case we probably should print it to the console.592 */593static void tape_3590_read_attmsg_async(struct tape_device *device)594{595	struct tape_request *request;596	char *buf;597 598	request = tape_alloc_request(3, 4096);599	if (IS_ERR(request))600		return;601	request->op = TO_READ_ATTMSG;602	buf = request->cpdata;603	buf[0] = PREP_RD_SS_DATA;604	buf[6] = RD_ATTMSG;	/* read att msg */605	tape_ccw_cc(request->cpaddr, PERFORM_SS_FUNC, 12, buf);606	tape_ccw_cc(request->cpaddr + 1, READ_SS_DATA, 4096 - 12, buf + 12);607	tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL);608	tape_do_io_async_free(device, request);609}610 611/*612 * These functions are used to schedule follow-up actions from within an613 * interrupt context (like unsolicited interrupts).614 * Note: the work handler is called by the system work queue. The tape615 * commands started by the handler need to be asynchrounous, otherwise616 * a deadlock can occur e.g. in case of a deferred cc=1 (see __tape_do_irq).617 */618struct work_handler_data {619	struct tape_device *device;620	enum tape_op        op;621	struct work_struct  work;622};623 624static void625tape_3590_work_handler(struct work_struct *work)626{627	struct work_handler_data *p =628		container_of(work, struct work_handler_data, work);629 630	switch (p->op) {631	case TO_MSEN:632		tape_3590_sense_medium_async(p->device);633		break;634	case TO_READ_ATTMSG:635		tape_3590_read_attmsg_async(p->device);636		break;637	case TO_CRYPT_ON:638		tape_3592_enable_crypt_async(p->device);639		break;640	case TO_CRYPT_OFF:641		tape_3592_disable_crypt_async(p->device);642		break;643	default:644		DBF_EVENT(3, "T3590: work handler undefined for "645			  "operation 0x%02x\n", p->op);646	}647	tape_put_device(p->device);648	kfree(p);649}650 651static int652tape_3590_schedule_work(struct tape_device *device, enum tape_op op)653{654	struct work_handler_data *p;655 656	if ((p = kzalloc(sizeof(*p), GFP_ATOMIC)) == NULL)657		return -ENOMEM;658 659	INIT_WORK(&p->work, tape_3590_work_handler);660 661	p->device = tape_get_device(device);662	p->op = op;663 664	queue_work(tape_3590_wq, &p->work);665	return 0;666}667 668static void tape_3590_med_state_set(struct tape_device *device,669				    struct tape_3590_med_sense *sense)670{671	struct tape390_crypt_info *c_info;672 673	c_info = &TAPE_3590_CRYPT_INFO(device);674 675	DBF_EVENT(6, "medium state: %x:%x\n", sense->macst, sense->masst);676	switch (sense->macst) {677	case 0x04:678	case 0x05:679	case 0x06:680		tape_med_state_set(device, MS_UNLOADED);681		TAPE_3590_CRYPT_INFO(device).medium_status = 0;682		return;683	case 0x08:684	case 0x09:685		tape_med_state_set(device, MS_LOADED);686		break;687	default:688		tape_med_state_set(device, MS_UNKNOWN);689		return;690	}691	c_info->medium_status |= TAPE390_MEDIUM_LOADED_MASK;692	if (sense->flags & MSENSE_CRYPT_MASK) {693		DBF_EVENT(6, "Medium is encrypted (%04x)\n", sense->flags);694		c_info->medium_status |= TAPE390_MEDIUM_ENCRYPTED_MASK;695	} else	{696		DBF_EVENT(6, "Medium is not encrypted %04x\n", sense->flags);697		c_info->medium_status &= ~TAPE390_MEDIUM_ENCRYPTED_MASK;698	}699}700 701/*702 * The done handler is called at device/channel end and wakes up the sleeping703 * process704 */705static int706tape_3590_done(struct tape_device *device, struct tape_request *request)707{708 709	DBF_EVENT(6, "%s done\n", tape_op_verbose[request->op]);710 711	switch (request->op) {712	case TO_BSB:713	case TO_BSF:714	case TO_DSE:715	case TO_FSB:716	case TO_FSF:717	case TO_LBL:718	case TO_RFO:719	case TO_RBA:720	case TO_REW:721	case TO_WRI:722	case TO_WTM:723	case TO_BLOCK:724	case TO_LOAD:725		tape_med_state_set(device, MS_LOADED);726		break;727	case TO_RUN:728		tape_med_state_set(device, MS_UNLOADED);729		tape_3590_schedule_work(device, TO_CRYPT_OFF);730		break;731	case TO_MSEN:732		tape_3590_med_state_set(device, request->cpdata);733		break;734	case TO_CRYPT_ON:735		TAPE_3590_CRYPT_INFO(device).status736			|= TAPE390_CRYPT_ON_MASK;737		*(device->modeset_byte) |= 0x03;738		break;739	case TO_CRYPT_OFF:740		TAPE_3590_CRYPT_INFO(device).status741			&= ~TAPE390_CRYPT_ON_MASK;742		*(device->modeset_byte) &= ~0x03;743		break;744	case TO_RBI:	/* RBI seems to succeed even without medium loaded. */745	case TO_NOP:	/* Same to NOP. */746	case TO_READ_CONFIG:747	case TO_READ_ATTMSG:748	case TO_DIS:749	case TO_ASSIGN:750	case TO_UNASSIGN:751	case TO_SIZE:752	case TO_KEKL_SET:753	case TO_KEKL_QUERY:754	case TO_RDC:755		break;756	}757	return TAPE_IO_SUCCESS;758}759 760/*761 * This function is called, when error recovery was successful762 */763static inline int764tape_3590_erp_succeeded(struct tape_device *device, struct tape_request *request)765{766	DBF_EVENT(3, "Error Recovery successful for %s\n",767		  tape_op_verbose[request->op]);768	return tape_3590_done(device, request);769}770 771/*772 * This function is called, when error recovery was not successful773 */774static inline int775tape_3590_erp_failed(struct tape_device *device, struct tape_request *request,776		     struct irb *irb, int rc)777{778	DBF_EVENT(3, "Error Recovery failed for %s\n",779		  tape_op_verbose[request->op]);780	tape_dump_sense_dbf(device, request, irb);781	return rc;782}783 784/*785 * Error Recovery do retry786 */787static inline int788tape_3590_erp_retry(struct tape_device *device, struct tape_request *request,789		    struct irb *irb)790{791	DBF_EVENT(2, "Retry: %s\n", tape_op_verbose[request->op]);792	tape_dump_sense_dbf(device, request, irb);793	return TAPE_IO_RETRY;794}795 796/*797 * Handle unsolicited interrupts798 */799static int800tape_3590_unsolicited_irq(struct tape_device *device, struct irb *irb)801{802	if (irb->scsw.cmd.dstat == DEV_STAT_CHN_END)803		/* Probably result of halt ssch */804		return TAPE_IO_PENDING;805	else if (irb->scsw.cmd.dstat == 0x85)806		/* Device Ready */807		DBF_EVENT(3, "unsol.irq! tape ready: %08x\n", device->cdev_id);808	else if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {809		tape_3590_schedule_work(device, TO_READ_ATTMSG);810	} else {811		DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id);812		tape_dump_sense_dbf(device, NULL, irb);813	}814	/* check medium state */815	tape_3590_schedule_work(device, TO_MSEN);816	return TAPE_IO_SUCCESS;817}818 819/*820 * Basic Recovery routine821 */822static int823tape_3590_erp_basic(struct tape_device *device, struct tape_request *request,824		    struct irb *irb, int rc)825{826	struct tape_3590_sense *sense;827 828	sense = (struct tape_3590_sense *) irb->ecw;829 830	switch (sense->bra) {831	case SENSE_BRA_PER:832		return tape_3590_erp_failed(device, request, irb, rc);833	case SENSE_BRA_CONT:834		return tape_3590_erp_succeeded(device, request);835	case SENSE_BRA_RE:836		return tape_3590_erp_retry(device, request, irb);837	case SENSE_BRA_DRE:838		return tape_3590_erp_failed(device, request, irb, rc);839	default:840		BUG();841		return TAPE_IO_STOP;842	}843}844 845/*846 *  RDL: Read Device (buffered) log847 */848static int849tape_3590_erp_read_buf_log(struct tape_device *device,850			   struct tape_request *request, struct irb *irb)851{852	/*853	 * We just do the basic error recovery at the moment (retry).854	 * Perhaps in the future, we read the log and dump it somewhere...855	 */856	return tape_3590_erp_basic(device, request, irb, -EIO);857}858 859/*860 *  SWAP: Swap Devices861 */862static int863tape_3590_erp_swap(struct tape_device *device, struct tape_request *request,864		   struct irb *irb)865{866	/*867	 * This error recovery should swap the tapes868	 * if the original has a problem. The operation869	 * should proceed with the new tape... this870	 * should probably be done in user space!871	 */872	dev_warn (&device->cdev->dev, "The tape medium must be loaded into a "873		"different tape unit\n");874	return tape_3590_erp_basic(device, request, irb, -EIO);875}876 877/*878 *  LBY: Long Busy879 */880static int881tape_3590_erp_long_busy(struct tape_device *device,882			struct tape_request *request, struct irb *irb)883{884	DBF_EVENT(6, "Device is busy\n");885	return TAPE_IO_LONG_BUSY;886}887 888/*889 *  SPI: Special Intercept890 */891static int892tape_3590_erp_special_interrupt(struct tape_device *device,893				struct tape_request *request, struct irb *irb)894{895	return tape_3590_erp_basic(device, request, irb, -EIO);896}897 898/*899 *  RDA: Read Alternate900 */901static int902tape_3590_erp_read_alternate(struct tape_device *device,903			     struct tape_request *request, struct irb *irb)904{905	struct tape_3590_disc_data *data;906 907	/*908	 * The issued Read Backward or Read Previous command is not909	 * supported by the device910	 * The recovery action should be to issue another command:911	 * Read Revious: if Read Backward is not supported912	 * Read Backward: if Read Previous is not supported913	 */914	data = device->discdata;915	if (data->read_back_op == READ_PREVIOUS) {916		DBF_EVENT(2, "(%08x): No support for READ_PREVIOUS command\n",917			  device->cdev_id);918		data->read_back_op = READ_BACKWARD;919	} else {920		DBF_EVENT(2, "(%08x): No support for READ_BACKWARD command\n",921			  device->cdev_id);922		data->read_back_op = READ_PREVIOUS;923	}924	tape_3590_read_opposite(device, request);925	return tape_3590_erp_retry(device, request, irb);926}927 928/*929 * Error Recovery read opposite930 */931static int932tape_3590_erp_read_opposite(struct tape_device *device,933			    struct tape_request *request, struct irb *irb)934{935	switch (request->op) {936	case TO_RFO:937		/*938		 * We did read forward, but the data could not be read.939		 * We will read backward and then skip forward again.940		 */941		tape_3590_read_opposite(device, request);942		return tape_3590_erp_retry(device, request, irb);943	case TO_RBA:944		/* We tried to read forward and backward, but hat no success */945		return tape_3590_erp_failed(device, request, irb, -EIO);946		break;947	default:948		return tape_3590_erp_failed(device, request, irb, -EIO);949	}950}951 952/*953 * Print an MIM (Media Information  Message) (message code f0)954 */955static void956tape_3590_print_mim_msg_f0(struct tape_device *device, struct irb *irb)957{958	struct tape_3590_sense *sense;959	char *exception, *service;960 961	exception = kmalloc(BUFSIZE, GFP_ATOMIC);962	service = kmalloc(BUFSIZE, GFP_ATOMIC);963 964	if (!exception || !service)965		goto out_nomem;966 967	sense = (struct tape_3590_sense *) irb->ecw;968	/* Exception Message */969	switch (sense->fmt.f70.emc) {970	case 0x02:971		snprintf(exception, BUFSIZE, "Data degraded");972		break;973	case 0x03:974		snprintf(exception, BUFSIZE, "Data degraded in partition %i",975			sense->fmt.f70.mp);976		break;977	case 0x04:978		snprintf(exception, BUFSIZE, "Medium degraded");979		break;980	case 0x05:981		snprintf(exception, BUFSIZE, "Medium degraded in partition %i",982			sense->fmt.f70.mp);983		break;984	case 0x06:985		snprintf(exception, BUFSIZE, "Block 0 Error");986		break;987	case 0x07:988		snprintf(exception, BUFSIZE, "Medium Exception 0x%02x",989			sense->fmt.f70.md);990		break;991	default:992		snprintf(exception, BUFSIZE, "0x%02x",993			sense->fmt.f70.emc);994		break;995	}996	/* Service Message */997	switch (sense->fmt.f70.smc) {998	case 0x02:999		snprintf(service, BUFSIZE, "Reference Media maintenance "1000			"procedure %i", sense->fmt.f70.md);1001		break;1002	default:1003		snprintf(service, BUFSIZE, "0x%02x",1004			sense->fmt.f70.smc);1005		break;1006	}1007 1008	dev_warn (&device->cdev->dev, "Tape media information: exception %s, "1009		"service %s\n", exception, service);1010 1011out_nomem:1012	kfree(exception);1013	kfree(service);1014}1015 1016/*1017 * Print an I/O Subsystem Service Information Message (message code f1)1018 */1019static void1020tape_3590_print_io_sim_msg_f1(struct tape_device *device, struct irb *irb)1021{1022	struct tape_3590_sense *sense;1023	char *exception, *service;1024 1025	exception = kmalloc(BUFSIZE, GFP_ATOMIC);1026	service = kmalloc(BUFSIZE, GFP_ATOMIC);1027 1028	if (!exception || !service)1029		goto out_nomem;1030 1031	sense = (struct tape_3590_sense *) irb->ecw;1032	/* Exception Message */1033	switch (sense->fmt.f71.emc) {1034	case 0x01:1035		snprintf(exception, BUFSIZE, "Effect of failure is unknown");1036		break;1037	case 0x02:1038		snprintf(exception, BUFSIZE, "CU Exception - no performance "1039			"impact");1040		break;1041	case 0x03:1042		snprintf(exception, BUFSIZE, "CU Exception on channel "1043			"interface 0x%02x", sense->fmt.f71.md[0]);1044		break;1045	case 0x04:1046		snprintf(exception, BUFSIZE, "CU Exception on device path "1047			"0x%02x", sense->fmt.f71.md[0]);1048		break;1049	case 0x05:1050		snprintf(exception, BUFSIZE, "CU Exception on library path "1051			"0x%02x", sense->fmt.f71.md[0]);1052		break;1053	case 0x06:1054		snprintf(exception, BUFSIZE, "CU Exception on node 0x%02x",1055			sense->fmt.f71.md[0]);1056		break;1057	case 0x07:1058		snprintf(exception, BUFSIZE, "CU Exception on partition "1059			"0x%02x", sense->fmt.f71.md[0]);1060		break;1061	default:1062		snprintf(exception, BUFSIZE, "0x%02x",1063			sense->fmt.f71.emc);1064	}1065	/* Service Message */1066	switch (sense->fmt.f71.smc) {1067	case 0x01:1068		snprintf(service, BUFSIZE, "Repair impact is unknown");1069		break;1070	case 0x02:1071		snprintf(service, BUFSIZE, "Repair will not impact cu "1072			"performance");1073		break;1074	case 0x03:1075		if (sense->fmt.f71.mdf == 0)1076			snprintf(service, BUFSIZE, "Repair will disable node "1077				"0x%x on CU", sense->fmt.f71.md[1]);1078		else1079			snprintf(service, BUFSIZE, "Repair will disable "1080				"nodes (0x%x-0x%x) on CU", sense->fmt.f71.md[1],1081				sense->fmt.f71.md[2]);1082		break;1083	case 0x04:1084		if (sense->fmt.f71.mdf == 0)1085			snprintf(service, BUFSIZE, "Repair will disable "1086				"channel path 0x%x on CU",1087				sense->fmt.f71.md[1]);1088		else1089			snprintf(service, BUFSIZE, "Repair will disable channel"1090				" paths (0x%x-0x%x) on CU",1091				sense->fmt.f71.md[1], sense->fmt.f71.md[2]);1092		break;1093	case 0x05:1094		if (sense->fmt.f71.mdf == 0)1095			snprintf(service, BUFSIZE, "Repair will disable device"1096				" path 0x%x on CU", sense->fmt.f71.md[1]);1097		else1098			snprintf(service, BUFSIZE, "Repair will disable device"1099				" paths (0x%x-0x%x) on CU",1100				sense->fmt.f71.md[1], sense->fmt.f71.md[2]);1101		break;1102	case 0x06:1103		if (sense->fmt.f71.mdf == 0)1104			snprintf(service, BUFSIZE, "Repair will disable "1105				"library path 0x%x on CU",1106				sense->fmt.f71.md[1]);1107		else1108			snprintf(service, BUFSIZE, "Repair will disable "1109				"library paths (0x%x-0x%x) on CU",1110				sense->fmt.f71.md[1], sense->fmt.f71.md[2]);1111		break;1112	case 0x07:1113		snprintf(service, BUFSIZE, "Repair will disable access to CU");1114		break;1115	default:1116		snprintf(service, BUFSIZE, "0x%02x",1117			sense->fmt.f71.smc);1118	}1119 1120	dev_warn (&device->cdev->dev, "I/O subsystem information: exception"1121		" %s, service %s\n", exception, service);1122out_nomem:1123	kfree(exception);1124	kfree(service);1125}1126 1127/*1128 * Print an Device Subsystem Service Information Message (message code f2)1129 */1130static void1131tape_3590_print_dev_sim_msg_f2(struct tape_device *device, struct irb *irb)1132{1133	struct tape_3590_sense *sense;1134	char *exception, *service;1135 1136	exception = kmalloc(BUFSIZE, GFP_ATOMIC);1137	service = kmalloc(BUFSIZE, GFP_ATOMIC);1138 1139	if (!exception || !service)1140		goto out_nomem;1141 1142	sense = (struct tape_3590_sense *) irb->ecw;1143	/* Exception Message */1144	switch (sense->fmt.f71.emc) {1145	case 0x01:1146		snprintf(exception, BUFSIZE, "Effect of failure is unknown");1147		break;1148	case 0x02:1149		snprintf(exception, BUFSIZE, "DV Exception - no performance"1150			" impact");1151		break;1152	case 0x03:1153		snprintf(exception, BUFSIZE, "DV Exception on channel "1154			"interface 0x%02x", sense->fmt.f71.md[0]);1155		break;1156	case 0x04:1157		snprintf(exception, BUFSIZE, "DV Exception on loader 0x%02x",1158			sense->fmt.f71.md[0]);1159		break;1160	case 0x05:1161		snprintf(exception, BUFSIZE, "DV Exception on message display"1162			" 0x%02x", sense->fmt.f71.md[0]);1163		break;1164	case 0x06:1165		snprintf(exception, BUFSIZE, "DV Exception in tape path");1166		break;1167	case 0x07:1168		snprintf(exception, BUFSIZE, "DV Exception in drive");1169		break;1170	default:1171		snprintf(exception, BUFSIZE, "0x%02x",1172			sense->fmt.f71.emc);1173	}1174	/* Service Message */1175	switch (sense->fmt.f71.smc) {1176	case 0x01:1177		snprintf(service, BUFSIZE, "Repair impact is unknown");1178		break;1179	case 0x02:1180		snprintf(service, BUFSIZE, "Repair will not impact device "1181			"performance");1182		break;1183	case 0x03:1184		if (sense->fmt.f71.mdf == 0)1185			snprintf(service, BUFSIZE, "Repair will disable "1186				"channel path 0x%x on DV",1187				sense->fmt.f71.md[1]);1188		else1189			snprintf(service, BUFSIZE, "Repair will disable "1190				"channel path (0x%x-0x%x) on DV",1191				sense->fmt.f71.md[1], sense->fmt.f71.md[2]);1192		break;1193	case 0x04:1194		if (sense->fmt.f71.mdf == 0)1195			snprintf(service, BUFSIZE, "Repair will disable "1196				"interface 0x%x on DV", sense->fmt.f71.md[1]);1197		else1198			snprintf(service, BUFSIZE, "Repair will disable "1199				"interfaces (0x%x-0x%x) on DV",1200				sense->fmt.f71.md[1], sense->fmt.f71.md[2]);1201		break;1202	case 0x05:1203		if (sense->fmt.f71.mdf == 0)1204			snprintf(service, BUFSIZE, "Repair will disable loader"1205				" 0x%x on DV", sense->fmt.f71.md[1]);1206		else1207			snprintf(service, BUFSIZE, "Repair will disable loader"1208				" (0x%x-0x%x) on DV",1209				sense->fmt.f71.md[1], sense->fmt.f71.md[2]);1210		break;1211	case 0x07:1212		snprintf(service, BUFSIZE, "Repair will disable access to DV");1213		break;1214	case 0x08:1215		if (sense->fmt.f71.mdf == 0)1216			snprintf(service, BUFSIZE, "Repair will disable "1217				"message display 0x%x on DV",1218				sense->fmt.f71.md[1]);1219		else1220			snprintf(service, BUFSIZE, "Repair will disable "1221				"message displays (0x%x-0x%x) on DV",1222				 sense->fmt.f71.md[1], sense->fmt.f71.md[2]);1223		break;1224	case 0x09:1225		snprintf(service, BUFSIZE, "Clean DV");1226		break;1227	default:1228		snprintf(service, BUFSIZE, "0x%02x",1229			sense->fmt.f71.smc);1230	}1231 1232	dev_warn (&device->cdev->dev, "Device subsystem information: exception"1233		" %s, service %s\n", exception, service);1234out_nomem:1235	kfree(exception);1236	kfree(service);1237}1238 1239/*1240 * Print standard ERA Message1241 */1242static void1243tape_3590_print_era_msg(struct tape_device *device, struct irb *irb)1244{1245	struct tape_3590_sense *sense;1246 1247	sense = (struct tape_3590_sense *) irb->ecw;1248	if (sense->mc == 0)1249		return;1250	if ((sense->mc > 0) && (sense->mc < TAPE_3590_MAX_MSG)) {1251		if (tape_3590_msg[sense->mc] != NULL)1252			dev_warn (&device->cdev->dev, "The tape unit has "1253				"issued sense message %s\n",1254				tape_3590_msg[sense->mc]);1255		else1256			dev_warn (&device->cdev->dev, "The tape unit has "1257				"issued an unknown sense message code 0x%x\n",1258				sense->mc);1259		return;1260	}1261	if (sense->mc == 0xf0) {1262		/* Standard Media Information Message */1263		dev_warn (&device->cdev->dev, "MIM SEV=%i, MC=%02x, ES=%x/%x, "1264			"RC=%02x-%04x-%02x\n", sense->fmt.f70.sev, sense->mc,1265			sense->fmt.f70.emc, sense->fmt.f70.smc,1266			sense->fmt.f70.refcode, sense->fmt.f70.mid,1267			sense->fmt.f70.fid);1268		tape_3590_print_mim_msg_f0(device, irb);1269		return;1270	}1271	if (sense->mc == 0xf1) {1272		/* Standard I/O Subsystem Service Information Message */1273		dev_warn (&device->cdev->dev, "IOSIM SEV=%i, DEVTYPE=3590/%02x,"1274			" MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n",1275			sense->fmt.f71.sev, device->cdev->id.dev_model,1276			sense->mc, sense->fmt.f71.emc, sense->fmt.f71.smc,1277			sense->fmt.f71.refcode1, sense->fmt.f71.refcode2,1278			sense->fmt.f71.refcode3);1279		tape_3590_print_io_sim_msg_f1(device, irb);1280		return;1281	}1282	if (sense->mc == 0xf2) {1283		/* Standard Device Service Information Message */1284		dev_warn (&device->cdev->dev, "DEVSIM SEV=%i, DEVTYPE=3590/%02x"1285			", MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n",1286			sense->fmt.f71.sev, device->cdev->id.dev_model,1287			sense->mc, sense->fmt.f71.emc, sense->fmt.f71.smc,1288			sense->fmt.f71.refcode1, sense->fmt.f71.refcode2,1289			sense->fmt.f71.refcode3);1290		tape_3590_print_dev_sim_msg_f2(device, irb);1291		return;1292	}1293	if (sense->mc == 0xf3) {1294		/* Standard Library Service Information Message */1295		return;1296	}1297	dev_warn (&device->cdev->dev, "The tape unit has issued an unknown "1298		"sense message code %x\n", sense->mc);1299}1300 1301static int tape_3590_crypt_error(struct tape_device *device,1302				 struct tape_request *request, struct irb *irb)1303{1304	u8 cu_rc;1305	u16 ekm_rc2;1306	char *sense;1307 1308	sense = ((struct tape_3590_sense *) irb->ecw)->fmt.data;1309	cu_rc = sense[0];1310	ekm_rc2 = *((u16*) &sense[10]);1311	if ((cu_rc == 0) && (ekm_rc2 == 0xee31))1312		/* key not defined on EKM */1313		return tape_3590_erp_basic(device, request, irb, -EKEYREJECTED);1314	if ((cu_rc == 1) || (cu_rc == 2))1315		/* No connection to EKM */1316		return tape_3590_erp_basic(device, request, irb, -ENOTCONN);1317 1318	dev_err (&device->cdev->dev, "The tape unit failed to obtain the "1319		"encryption key from EKM\n");1320 1321	return tape_3590_erp_basic(device, request, irb, -ENOKEY);1322}1323 1324/*1325 *  3590 error Recovery routine:1326 *  If possible, it tries to recover from the error. If this is not possible,1327 *  inform the user about the problem.1328 */1329static int1330tape_3590_unit_check(struct tape_device *device, struct tape_request *request,1331		     struct irb *irb)1332{1333	struct tape_3590_sense *sense;1334 1335	sense = (struct tape_3590_sense *) irb->ecw;1336 1337	DBF_EVENT(6, "Unit Check: RQC = %x\n", sense->rc_rqc);1338 1339	/*1340	 * First check all RC-QRCs where we want to do something special1341	 *   - "break":     basic error recovery is done1342	 *   - "goto out:": just print error message if available1343	 */1344	switch (sense->rc_rqc) {1345 1346	case 0x1110:1347		tape_3590_print_era_msg(device, irb);1348		return tape_3590_erp_read_buf_log(device, request, irb);1349 1350	case 0x2011:1351		tape_3590_print_era_msg(device, irb);1352		return tape_3590_erp_read_alternate(device, request, irb);1353 1354	case 0x2230:1355	case 0x2231:1356		tape_3590_print_era_msg(device, irb);1357		return tape_3590_erp_special_interrupt(device, request, irb);1358	case 0x2240:1359		return tape_3590_crypt_error(device, request, irb);1360 1361	case 0x3010:1362		DBF_EVENT(2, "(%08x): Backward at Beginning of Partition\n",1363			  device->cdev_id);1364		return tape_3590_erp_basic(device, request, irb, -ENOSPC);1365	case 0x3012:1366		DBF_EVENT(2, "(%08x): Forward at End of Partition\n",1367			  device->cdev_id);1368		return tape_3590_erp_basic(device, request, irb, -ENOSPC);1369	case 0x3020:1370		DBF_EVENT(2, "(%08x): End of Data Mark\n", device->cdev_id);1371		return tape_3590_erp_basic(device, request, irb, -ENOSPC);1372 1373	case 0x3122:1374		DBF_EVENT(2, "(%08x): Rewind Unload initiated\n",1375			  device->cdev_id);1376		return tape_3590_erp_basic(device, request, irb, -EIO);1377	case 0x3123:1378		DBF_EVENT(2, "(%08x): Rewind Unload complete\n",1379			  device->cdev_id);1380		tape_med_state_set(device, MS_UNLOADED);1381		tape_3590_schedule_work(device, TO_CRYPT_OFF);1382		return tape_3590_erp_basic(device, request, irb, 0);1383 1384	case 0x4010:1385		/*1386		 * print additional msg since default msg1387		 * "device intervention" is not very meaningfull1388		 */1389		tape_med_state_set(device, MS_UNLOADED);1390		tape_3590_schedule_work(device, TO_CRYPT_OFF);1391		return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM);1392	case 0x4012:		/* Device Long Busy */1393		/* XXX: Also use long busy handling here? */1394		DBF_EVENT(6, "(%08x): LONG BUSY\n", device->cdev_id);1395		tape_3590_print_era_msg(device, irb);1396		return tape_3590_erp_basic(device, request, irb, -EBUSY);1397	case 0x4014:1398		DBF_EVENT(6, "(%08x): Crypto LONG BUSY\n", device->cdev_id);1399		return tape_3590_erp_long_busy(device, request, irb);1400 1401	case 0x5010:1402		if (sense->rac == 0xd0) {1403			/* Swap */1404			tape_3590_print_era_msg(device, irb);1405			return tape_3590_erp_swap(device, request, irb);1406		}1407		if (sense->rac == 0x26) {1408			/* Read Opposite */1409			tape_3590_print_era_msg(device, irb);1410			return tape_3590_erp_read_opposite(device, request,1411							   irb);1412		}1413		return tape_3590_erp_basic(device, request, irb, -EIO);1414	case 0x5020:1415	case 0x5021:1416	case 0x5022:1417	case 0x5040:1418	case 0x5041:1419	case 0x5042:1420		tape_3590_print_era_msg(device, irb);1421		return tape_3590_erp_swap(device, request, irb);1422 1423	case 0x5110:1424	case 0x5111:1425		return tape_3590_erp_basic(device, request, irb, -EMEDIUMTYPE);1426 1427	case 0x5120:1428	case 0x1120:1429		tape_med_state_set(device, MS_UNLOADED);1430		tape_3590_schedule_work(device, TO_CRYPT_OFF);1431		return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM);1432 1433	case 0x6020:1434		return tape_3590_erp_basic(device, request, irb, -EMEDIUMTYPE);1435 1436	case 0x8011:1437		return tape_3590_erp_basic(device, request, irb, -EPERM);1438	case 0x8013:1439		dev_warn (&device->cdev->dev, "A different host has privileged"1440			" access to the tape unit\n");1441		return tape_3590_erp_basic(device, request, irb, -EPERM);1442	default:1443		return tape_3590_erp_basic(device, request, irb, -EIO);1444	}1445}1446 1447/*1448 * 3590 interrupt handler:1449 */1450static int1451tape_3590_irq(struct tape_device *device, struct tape_request *request,1452	      struct irb *irb)1453{1454	if (request == NULL)1455		return tape_3590_unsolicited_irq(device, irb);1456 1457	if ((irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) &&1458	    (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) &&1459	    (request->op == TO_WRI)) {1460		/* Write at end of volume */1461		DBF_EVENT(2, "End of volume\n");1462		return tape_3590_erp_failed(device, request, irb, -ENOSPC);1463	}1464 1465	if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK)1466		return tape_3590_unit_check(device, request, irb);1467 1468	if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {1469		if (irb->scsw.cmd.dstat == DEV_STAT_UNIT_EXCEP) {1470			if (request->op == TO_FSB || request->op == TO_BSB)1471				request->rescnt++;1472			else1473				DBF_EVENT(5, "Unit Exception!\n");1474		}1475 1476		return tape_3590_done(device, request);1477	}1478 1479	if (irb->scsw.cmd.dstat & DEV_STAT_CHN_END) {1480		DBF_EVENT(2, "channel end\n");1481		return TAPE_IO_PENDING;1482	}1483 1484	if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {1485		DBF_EVENT(2, "Unit Attention when busy..\n");1486		return TAPE_IO_PENDING;1487	}1488 1489	DBF_EVENT(6, "xunknownirq\n");1490	tape_dump_sense_dbf(device, request, irb);1491	return TAPE_IO_STOP;1492}1493 1494 1495static int tape_3590_read_dev_chars(struct tape_device *device,1496				    struct tape_3590_rdc_data *rdc_data)1497{1498	int rc;1499	struct tape_request *request;1500 1501	request = tape_alloc_request(1, sizeof(*rdc_data));1502	if (IS_ERR(request))1503		return PTR_ERR(request);1504	request->op = TO_RDC;1505	tape_ccw_end(request->cpaddr, CCW_CMD_RDC, sizeof(*rdc_data),1506		     request->cpdata);1507	rc = tape_do_io(device, request);1508	if (rc == 0)1509		memcpy(rdc_data, request->cpdata, sizeof(*rdc_data));1510	tape_free_request(request);1511	return rc;1512}1513 1514/*1515 * Setup device function1516 */1517static int1518tape_3590_setup_device(struct tape_device *device)1519{1520	int rc;1521	struct tape_3590_disc_data *data;1522	struct tape_3590_rdc_data *rdc_data;1523 1524	DBF_EVENT(6, "3590 device setup\n");1525	data = kzalloc(sizeof(struct tape_3590_disc_data), GFP_KERNEL | GFP_DMA);1526	if (data == NULL)1527		return -ENOMEM;1528	data->read_back_op = READ_PREVIOUS;1529	device->discdata = data;1530 1531	rdc_data = kmalloc(sizeof(*rdc_data), GFP_KERNEL | GFP_DMA);1532	if (!rdc_data) {1533		rc = -ENOMEM;1534		goto fail_kmalloc;1535	}1536	rc = tape_3590_read_dev_chars(device, rdc_data);1537	if (rc) {1538		DBF_LH(3, "Read device characteristics failed!\n");1539		goto fail_rdc_data;1540	}1541	rc = tape_std_assign(device);1542	if (rc)1543		goto fail_rdc_data;1544	if (rdc_data->data[31] == 0x13) {1545		data->crypt_info.capability |= TAPE390_CRYPT_SUPPORTED_MASK;1546		tape_3592_disable_crypt(device);1547	} else {1548		DBF_EVENT(6, "Device has NO crypto support\n");1549	}1550	/* Try to find out if medium is loaded */1551	rc = tape_3590_sense_medium(device);1552	if (rc) {1553		DBF_LH(3, "3590 medium sense returned %d\n", rc);1554		goto fail_rdc_data;1555	}1556	return 0;1557 1558fail_rdc_data:1559	kfree(rdc_data);1560fail_kmalloc:1561	kfree(data);1562	return rc;1563}1564 1565/*1566 * Cleanup device function1567 */1568static void1569tape_3590_cleanup_device(struct tape_device *device)1570{1571	flush_workqueue(tape_3590_wq);1572	tape_std_unassign(device);1573 1574	kfree(device->discdata);1575	device->discdata = NULL;1576}1577 1578/*1579 * List of 3590 magnetic tape commands.1580 */1581static tape_mtop_fn tape_3590_mtop[TAPE_NR_MTOPS] = {1582	[MTRESET]	 = tape_std_mtreset,1583	[MTFSF]		 = tape_std_mtfsf,1584	[MTBSF]		 = tape_std_mtbsf,1585	[MTFSR]		 = tape_std_mtfsr,1586	[MTBSR]		 = tape_std_mtbsr,1587	[MTWEOF]	 = tape_std_mtweof,1588	[MTREW]		 = tape_std_mtrew,1589	[MTOFFL]	 = tape_std_mtoffl,1590	[MTNOP]		 = tape_std_mtnop,1591	[MTRETEN]	 = tape_std_mtreten,1592	[MTBSFM]	 = tape_std_mtbsfm,1593	[MTFSFM]	 = tape_std_mtfsfm,1594	[MTEOM]		 = tape_std_mteom,1595	[MTERASE]	 = tape_std_mterase,1596	[MTRAS1]	 = NULL,1597	[MTRAS2]	 = NULL,1598	[MTRAS3]	 = NULL,1599	[MTSETBLK]	 = tape_std_mtsetblk,1600	[MTSETDENSITY]	 = NULL,1601	[MTSEEK]	 = tape_3590_mtseek,1602	[MTTELL]	 = tape_3590_mttell,1603	[MTSETDRVBUFFER] = NULL,1604	[MTFSS]		 = NULL,1605	[MTBSS]		 = NULL,1606	[MTWSM]		 = NULL,1607	[MTLOCK]	 = NULL,1608	[MTUNLOCK]	 = NULL,1609	[MTLOAD]	 = tape_std_mtload,1610	[MTUNLOAD]	 = tape_std_mtunload,1611	[MTCOMPRESSION]	 = tape_std_mtcompression,1612	[MTSETPART]	 = NULL,1613	[MTMKPART]	 = NULL1614};1615 1616/*1617 * Tape discipline structure for 3590.1618 */1619static struct tape_discipline tape_discipline_3590 = {1620	.owner = THIS_MODULE,1621	.setup_device = tape_3590_setup_device,1622	.cleanup_device = tape_3590_cleanup_device,1623	.process_eov = tape_std_process_eov,1624	.irq = tape_3590_irq,1625	.read_block = tape_std_read_block,1626	.write_block = tape_std_write_block,1627	.ioctl_fn = tape_3590_ioctl,1628	.mtop_array = tape_3590_mtop1629};1630 1631static struct ccw_device_id tape_3590_ids[] = {1632	{CCW_DEVICE_DEVTYPE(0x3590, 0, 0x3590, 0), .driver_info = tape_3590},1633	{CCW_DEVICE_DEVTYPE(0x3592, 0, 0x3592, 0), .driver_info = tape_3592},1634	{ /* end of list */ }1635};1636 1637static int1638tape_3590_online(struct ccw_device *cdev)1639{1640	return tape_generic_online(dev_get_drvdata(&cdev->dev),1641				   &tape_discipline_3590);1642}1643 1644static struct ccw_driver tape_3590_driver = {1645	.driver = {1646		.name = "tape_3590",1647		.owner = THIS_MODULE,1648	},1649	.ids = tape_3590_ids,1650	.probe = tape_generic_probe,1651	.remove = tape_generic_remove,1652	.set_offline = tape_generic_offline,1653	.set_online = tape_3590_online,1654	.int_class = IRQIO_TAP,1655};1656 1657/*1658 * Setup discipline structure.1659 */1660static int1661tape_3590_init(void)1662{1663	int rc;1664 1665	TAPE_DBF_AREA = debug_register("tape_3590", 2, 2, 4 * sizeof(long));1666	debug_register_view(TAPE_DBF_AREA, &debug_sprintf_view);1667#ifdef DBF_LIKE_HELL1668	debug_set_level(TAPE_DBF_AREA, 6);1669#endif1670 1671	DBF_EVENT(3, "3590 init\n");1672 1673	tape_3590_wq = alloc_workqueue("tape_3590", 0, 0);1674	if (!tape_3590_wq)1675		return -ENOMEM;1676 1677	/* Register driver for 3590 tapes. */1678	rc = ccw_driver_register(&tape_3590_driver);1679	if (rc) {1680		destroy_workqueue(tape_3590_wq);1681		DBF_EVENT(3, "3590 init failed\n");1682	} else1683		DBF_EVENT(3, "3590 registered\n");1684	return rc;1685}1686 1687static void1688tape_3590_exit(void)1689{1690	ccw_driver_unregister(&tape_3590_driver);1691	destroy_workqueue(tape_3590_wq);1692	debug_unregister(TAPE_DBF_AREA);1693}1694 1695MODULE_DEVICE_TABLE(ccw, tape_3590_ids);1696MODULE_AUTHOR("(C) 2001,2006 IBM Corporation");1697MODULE_DESCRIPTION("Linux on zSeries channel attached 3590 tape device driver");1698MODULE_LICENSE("GPL");1699 1700module_init(tape_3590_init);1701module_exit(tape_3590_exit);1702