예제 #1
0
/*
 * Disable encryption
 */
static int tape_3592_disable_crypt(struct tape_device *device)
{
	struct tape_request *request;
	char *data;

	DBF_EVENT(6, "tape_3592_disable_crypt\n");
	if (!crypt_supported(device))
		return -ENOSYS;
	request = tape_alloc_request(2, 72);
	if (IS_ERR(request))
		return PTR_ERR(request);
	data = request->cpdata;
	memset(data,0,72);

	data[0]       = 0x05;
	data[36 + 0]  = 0x03;
	data[36 + 1]  = 0x03;
	data[36 + 35] = 0x32;

	request->op = TO_CRYPT_OFF;
	tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data);
	tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36);

	return tape_do_io_free(device, request);
}
static struct tape_request *__tape_3592_enable_crypt(struct tape_device *device)
{
	struct tape_request *request;
	char *data;

	DBF_EVENT(6, "tape_3592_enable_crypt\n");
	if (!crypt_supported(device))
		return ERR_PTR(-ENOSYS);
	request = tape_alloc_request(2, 72);
	if (IS_ERR(request))
		return request;
	data = request->cpdata;
	memset(data,0,72);

	data[0]       = 0x05;
	data[36 + 0]  = 0x03;
	data[36 + 1]  = 0x03;
	data[36 + 4]  = 0x40;
	data[36 + 6]  = 0x01;
	data[36 + 14] = 0x2f;
	data[36 + 18] = 0xc3;
	data[36 + 35] = 0x72;
	request->op = TO_CRYPT_ON;
	tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data);
	tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36);
	return request;
}
예제 #3
0
/*
 * Set KEKLs
 */
static int tape_3592_kekl_set(struct tape_device *device,
			      struct tape390_kekl_pair *ext_kekls)
{
	struct tape_request *request;
	struct tape3592_kekl_set_order *order;

	DBF_EVENT(6, "tape3592_kekl_set\n");
	if (check_ext_kekl_pair(ext_kekls)) {
		DBF_EVENT(6, "invalid kekls\n");
		return -EINVAL;
	}
	if (tape_3590_mttell(device, 0) != 0)
		return -EBADSLT;
	request = tape_alloc_request(1, sizeof(*order));
	if (IS_ERR(request))
		return PTR_ERR(request);
	order = request->cpdata;
	memset(order, 0, sizeof(*order));
	order->code = 0xe3;
	order->kekls.count = 2;
	ext_to_int_kekl(&ext_kekls->kekl[0], &order->kekls.kekl[0]);
	ext_to_int_kekl(&ext_kekls->kekl[1], &order->kekls.kekl[1]);
	request->op = TO_KEKL_SET;
	tape_ccw_end(request->cpaddr, PERF_SUBSYS_FUNC, sizeof(*order), order);

	return tape_do_io_free(device, request);
}
static void tape_3590_sense_medium_async(struct tape_device *device)
{
	struct tape_request *request;

	request = tape_alloc_request(1, 128);
	if (IS_ERR(request))
		return;
	request->op = TO_MSEN;
	tape_ccw_end(request->cpaddr, MEDIUM_SENSE, 128, request->cpdata);
	tape_do_io_async_free(device, request);
}
static void
tape_3590_read_opposite(struct tape_device *device,
			struct tape_request *request)
{
	struct tape_3590_disc_data *data;

	request->op = TO_RBA;
	tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
	data = device->discdata;
	tape_ccw_cc_idal(request->cpaddr + 1, data->read_back_op,
			 device->char_data.idal_buf);
	tape_ccw_cc(request->cpaddr + 2, FORSPACEBLOCK, 0, NULL);
	tape_ccw_end(request->cpaddr + 3, NOP, 0, NULL);
	DBF_EVENT(6, "xrop ccwg\n");
}
예제 #6
0
/*
 * MTSEEK: seek to the specified block.
 */
static int
tape_3590_mtseek(struct tape_device *device, int count)
{
	struct tape_request *request;

	DBF_EVENT(6, "xsee id: %x\n", count);
	request = tape_alloc_request(3, 4);
	if (IS_ERR(request))
		return PTR_ERR(request);
	request->op = TO_LBL;
	tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
	*(__u32 *) request->cpdata = count;
	tape_ccw_cc(request->cpaddr + 1, LOCATE, 4, request->cpdata);
	tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL);
	return tape_do_io_free(device, request);
}
예제 #7
0
static void tape_34xx_medium_sense_async(struct tape_device *device)
{
	struct tape_request *request;

	request = tape_alloc_request(1, 32);
	if (IS_ERR(request)) {
		DBF_EXCEPTION(6, "MSEN fail\n");
		return;
	}

	request->op = TO_MSEN;
	tape_ccw_end(request->cpaddr, SENSE, 32, request->cpdata);
	request->callback = (void *) __tape_34xx_medium_sense;
	request->callback_data = NULL;
	tape_do_io_async(device, request);
}
/*
 * Read Attention Msg
 * This should be done after an interrupt with attention bit (0x80)
 * in device state.
 *
 * After a "read attention message" request there are two possible
 * results:
 *
 * 1. A unit check is presented, when attention sense is present (e.g. when
 * a medium has been unloaded). The attention sense comes then
 * together with the unit check. The recovery action is either "retry"
 * (in case there is an attention message pending) or "permanent error".
 *
 * 2. The attention msg is written to the "read subsystem data" buffer.
 * In this case we probably should print it to the console.
 */
static void tape_3590_read_attmsg_async(struct tape_device *device)
{
	struct tape_request *request;
	char *buf;

	request = tape_alloc_request(3, 4096);
	if (IS_ERR(request))
		return;
	request->op = TO_READ_ATTMSG;
	buf = request->cpdata;
	buf[0] = PREP_RD_SS_DATA;
	buf[6] = RD_ATTMSG;	
	tape_ccw_cc(request->cpaddr, PERFORM_SS_FUNC, 12, buf);
	tape_ccw_cc(request->cpaddr + 1, READ_SS_DATA, 4096 - 12, buf + 12);
	tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL);
	tape_do_io_async_free(device, request);
}
예제 #9
0
static int tape_34xx_medium_sense(struct tape_device *device)
{
	struct tape_request *request;
	int rc;

	request = tape_alloc_request(1, 32);
	if (IS_ERR(request)) {
		DBF_EXCEPTION(6, "MSEN fail\n");
		return PTR_ERR(request);
	}

	request->op = TO_MSEN;
	tape_ccw_end(request->cpaddr, SENSE, 32, request->cpdata);
	rc = tape_do_io_interruptible(device, request);
	__tape_34xx_medium_sense(request);
	return rc;
}
예제 #10
0
/*
 * Medium sense for 34xx tapes. There is no 'real' medium sense call.
 * So we just do a normal sense.
 */
static int
tape_34xx_medium_sense(struct tape_device *device)
{
    struct tape_request *request;
    unsigned char       *sense;
    int                  rc;

    request = tape_alloc_request(1, 32);
    if (IS_ERR(request)) {
        DBF_EXCEPTION(6, "MSEN fail\n");
        return PTR_ERR(request);
    }

    request->op = TO_MSEN;
    tape_ccw_end(request->cpaddr, SENSE, 32, request->cpdata);

    rc = tape_do_io_interruptible(device, request);
    if (request->rc == 0) {
        sense = request->cpdata;

        /*
         * This isn't quite correct. But since INTERVENTION_REQUIRED
         * means that the drive is 'neither ready nor on-line' it is
         * only slightly inaccurate to say there is no tape loaded if
         * the drive isn't online...
         */
        if (sense[0] & SENSE_INTERVENTION_REQUIRED)
            tape_med_state_set(device, MS_UNLOADED);
        else
            tape_med_state_set(device, MS_LOADED);

        if (sense[1] & SENSE_WRITE_PROTECT)
            device->tape_generic_status |= GMT_WR_PROT(~0);
        else
            device->tape_generic_status &= ~GMT_WR_PROT(~0);
    } else {
        DBF_EVENT(4, "tape_34xx: medium sense failed with rc=%d\n",
                  request->rc);
    }
    tape_free_request(request);

    return rc;
}
예제 #11
0
/*
 * Read Opposite Error Recovery Function:
 * Used, when Read Forward does not work
 */
static void
tape_3590_read_opposite(struct tape_device *device,
			struct tape_request *request)
{
	struct tape_3590_disc_data *data;

	/*
	 * We have allocated 4 ccws in tape_std_read, so we can now
	 * transform the request to a read backward, followed by a
	 * forward space block.
	 */
	request->op = TO_RBA;
	tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
	data = device->discdata;
	tape_ccw_cc_idal(request->cpaddr + 1, data->read_back_op,
			 device->char_data.idal_buf);
	tape_ccw_cc(request->cpaddr + 2, FORSPACEBLOCK, 0, NULL);
	tape_ccw_end(request->cpaddr + 3, NOP, 0, NULL);
	DBF_EVENT(6, "xrop ccwg\n");
}
예제 #12
0
/*
 * Query KEKLs
 */
static int tape_3592_kekl_query(struct tape_device *device,
				struct tape390_kekl_pair *ext_kekls)
{
	struct tape_request *request;
	struct tape3592_kekl_query_order *order;
	struct tape3592_kekl_query_data *int_kekls;
	int rc;

	DBF_EVENT(6, "tape3592_kekl_query\n");
	int_kekls = kmalloc(sizeof(*int_kekls), GFP_KERNEL|GFP_DMA);
	if (!int_kekls)
		return -ENOMEM;
	request = tape_alloc_request(2, sizeof(*order));
	if (IS_ERR(request)) {
		rc = PTR_ERR(request);
		goto fail_malloc;
	}
	order = request->cpdata;
	memset(order,0,sizeof(*order));
	order->code = 0xe2;
	order->max_count = 2;
	request->op = TO_KEKL_QUERY;
	tape_ccw_cc(request->cpaddr, PERF_SUBSYS_FUNC, sizeof(*order), order);
	tape_ccw_end(request->cpaddr + 1, READ_SS_DATA, sizeof(*int_kekls),
		     int_kekls);
	rc = tape_do_io(device, request);
	if (rc)
		goto fail_request;
	int_to_ext_kekl_pair(&int_kekls->kekls, ext_kekls);

	rc = 0;
fail_request:
	tape_free_request(request);
fail_malloc:
	kfree(int_kekls);
	return rc;
}