/*
* drivers/s390/char/tape_34xx.c
* tape device discipline for 3480/3490 tapes.
*
* Copyright (C) IBM Corp. 2001,2006
* Author(s): Carsten Otte <cotte@de.ibm.com>
* Tuan Ngo-Anh <ngoanh@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/bio.h>
#include <linux/workqueue.h>
#define TAPE_DBF_AREA tape_34xx_dbf
#include "tape.h"
#include "tape_std.h"
#define PRINTK_HEADER "TAPE_34XX: "
/*
* Pointer to debug area.
*/
debug_info_t *TAPE_DBF_AREA = NULL;
EXPORT_SYMBOL(TAPE_DBF_AREA);
#define TAPE34XX_FMT_3480 0
#define TAPE34XX_FMT_3480_2_XF 1
#define TAPE34XX_FMT_3480_XF 2
struct tape_34xx_block_id {
unsigned int wrap : 1;
unsigned int segment : 7;
unsigned int format : 2;
unsigned int block : 22;
};
/*
* A list of block ID's is used to faster seek blocks.
*/
struct tape_34xx_sbid {
struct list_head list;
struct tape_34xx_block_id bid;
};
static void tape_34xx_delete_sbid_from(struct tape_device *, int);
/*
* 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(