^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * tape device discipline for 3480/3490 tapes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright IBM Corp. 2001, 2009
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author(s): Carsten Otte <cotte@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Tuan Ngo-Anh <ngoanh@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Martin Schwidefsky <schwidefsky@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define KMSG_COMPONENT "tape_34xx"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/bio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define TAPE_DBF_AREA tape_34xx_dbf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "tape.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "tape_std.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * Pointer to debug area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) debug_info_t *TAPE_DBF_AREA = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) EXPORT_SYMBOL(TAPE_DBF_AREA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define TAPE34XX_FMT_3480 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define TAPE34XX_FMT_3480_2_XF 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define TAPE34XX_FMT_3480_XF 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct tape_34xx_block_id {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) unsigned int wrap : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) unsigned int segment : 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) unsigned int format : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) unsigned int block : 22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * A list of block ID's is used to faster seek blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct tape_34xx_sbid {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct tape_34xx_block_id bid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static void tape_34xx_delete_sbid_from(struct tape_device *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * Medium sense for 34xx tapes. There is no 'real' medium sense call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * So we just do a normal sense.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static void __tape_34xx_medium_sense(struct tape_request *request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct tape_device *device = request->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) unsigned char *sense;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (request->rc == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) sense = request->cpdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * This isn't quite correct. But since INTERVENTION_REQUIRED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * means that the drive is 'neither ready nor on-line' it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * only slightly inaccurate to say there is no tape loaded if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * the drive isn't online...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (sense[0] & SENSE_INTERVENTION_REQUIRED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) tape_med_state_set(device, MS_UNLOADED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) tape_med_state_set(device, MS_LOADED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (sense[1] & SENSE_WRITE_PROTECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) device->tape_generic_status |= GMT_WR_PROT(~0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) device->tape_generic_status &= ~GMT_WR_PROT(~0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) DBF_EVENT(4, "tape_34xx: medium sense failed with rc=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) request->rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) tape_free_request(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static int tape_34xx_medium_sense(struct tape_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct tape_request *request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) request = tape_alloc_request(1, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (IS_ERR(request)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) DBF_EXCEPTION(6, "MSEN fail\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return PTR_ERR(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) request->op = TO_MSEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) tape_ccw_end(request->cpaddr, SENSE, 32, request->cpdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) rc = tape_do_io_interruptible(device, request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) __tape_34xx_medium_sense(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static void tape_34xx_medium_sense_async(struct tape_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct tape_request *request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) request = tape_alloc_request(1, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (IS_ERR(request)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) DBF_EXCEPTION(6, "MSEN fail\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) request->op = TO_MSEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) tape_ccw_end(request->cpaddr, SENSE, 32, request->cpdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) request->callback = (void *) __tape_34xx_medium_sense;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) request->callback_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) tape_do_io_async(device, request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct tape_34xx_work {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct tape_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) enum tape_op op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct work_struct work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * These functions are currently used only to schedule a medium_sense for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * later execution. This is because we get an interrupt whenever a medium
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * is inserted but cannot call tape_do_io* from an interrupt context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * Maybe that's useful for other actions we want to start from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * interrupt handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * Note: the work handler is called by the system work queue. The tape
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * commands started by the handler need to be asynchrounous, otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * a deadlock can occur e.g. in case of a deferred cc=1 (see __tape_do_irq).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) tape_34xx_work_handler(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct tape_34xx_work *p =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) container_of(work, struct tape_34xx_work, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct tape_device *device = p->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) switch(p->op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) case TO_MSEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) tape_34xx_medium_sense_async(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) DBF_EVENT(3, "T34XX: internal error: unknown work\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) tape_put_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) tape_34xx_schedule_work(struct tape_device *device, enum tape_op op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct tape_34xx_work *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if ((p = kzalloc(sizeof(*p), GFP_ATOMIC)) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) INIT_WORK(&p->work, tape_34xx_work_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) p->device = tape_get_device(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) p->op = op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) schedule_work(&p->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * Done Handler is called when dev stat = DEVICE-END (successful operation)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) tape_34xx_done(struct tape_request *request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) DBF_EVENT(6, "%s done\n", tape_op_verbose[request->op]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) switch (request->op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) case TO_DSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) case TO_RUN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) case TO_WRI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) case TO_WTM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) case TO_ASSIGN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) case TO_UNASSIGN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) tape_34xx_delete_sbid_from(request->device, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return TAPE_IO_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) tape_34xx_erp_failed(struct tape_request *request, int rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) DBF_EVENT(3, "Error recovery failed for %s (RC=%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) tape_op_verbose[request->op], rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) tape_34xx_erp_succeeded(struct tape_request *request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) DBF_EVENT(3, "Error Recovery successful for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) tape_op_verbose[request->op]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return tape_34xx_done(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) tape_34xx_erp_retry(struct tape_request *request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) DBF_EVENT(3, "xerp retr %s\n", tape_op_verbose[request->op]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return TAPE_IO_RETRY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * This function is called, when no request is outstanding and we get an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) tape_34xx_unsolicited_irq(struct tape_device *device, struct irb *irb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (irb->scsw.cmd.dstat == 0x85) { /* READY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* A medium was inserted in the drive. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) DBF_EVENT(6, "xuud med\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) tape_34xx_delete_sbid_from(device, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) tape_34xx_schedule_work(device, TO_MSEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) tape_dump_sense_dbf(device, NULL, irb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return TAPE_IO_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * Read Opposite Error Recovery Function:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * Used, when Read Forward does not work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) tape_34xx_erp_read_opposite(struct tape_device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct tape_request *request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (request->op == TO_RFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * We did read forward, but the data could not be read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * *correctly*. We transform the request to a read backward
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * and try again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) tape_std_read_backward(device, request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return tape_34xx_erp_retry(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * We tried to read forward and backward, but hat no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * success -> failed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) tape_34xx_erp_bug(struct tape_device *device, struct tape_request *request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct irb *irb, int no)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (request->op != TO_ASSIGN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) dev_err(&device->cdev->dev, "An unexpected condition %d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) "occurred in tape error recovery\n", no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) tape_dump_sense_dbf(device, request, irb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * Handle data overrun between cu and drive. The channel speed might
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * be too slow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) tape_34xx_erp_overrun(struct tape_device *device, struct tape_request *request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct irb *irb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (irb->ecw[3] == 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) dev_warn (&device->cdev->dev, "A data overrun occurred between"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) " the control unit and tape unit\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return tape_34xx_erp_bug(device, request, irb, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * Handle record sequence error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) tape_34xx_erp_sequence(struct tape_device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) struct tape_request *request, struct irb *irb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (irb->ecw[3] == 0x41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * cu detected incorrect block-id sequence on tape.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) dev_warn (&device->cdev->dev, "The block ID sequence on the "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) "tape is incorrect\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * Record sequence error bit is set, but erpa does not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * show record sequence error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return tape_34xx_erp_bug(device, request, irb, -2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * This function analyses the tape's sense-data in case of a unit-check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * If possible, it tries to recover from the error. Else the user is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * informed about the problem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct irb *irb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) int inhibit_cu_recovery;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) __u8* sense;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) inhibit_cu_recovery = (*device->modeset_byte & 0x80) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) sense = irb->ecw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) sense[0] & SENSE_COMMAND_REJECT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) sense[1] & SENSE_WRITE_PROTECT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) request->op == TO_DSE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) request->op == TO_WRI ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) request->op == TO_WTM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) /* medium is write protected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return tape_34xx_erp_failed(request, -EACCES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return tape_34xx_erp_bug(device, request, irb, -3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * Special cases for various tape-states when reaching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) * end of recorded area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * FIXME: Maybe a special case of the special case:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * sense[0] == SENSE_EQUIPMENT_CHECK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * sense[1] == SENSE_DRIVE_ONLINE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * sense[3] == 0x47 (Volume Fenced)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * This was caused by continued FSF or FSR after an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * 'End Of Data'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if ((
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) sense[0] == SENSE_DATA_CHECK ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) sense[0] == SENSE_EQUIPMENT_CHECK ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) sense[0] == SENSE_EQUIPMENT_CHECK + SENSE_DEFERRED_UNIT_CHECK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) ) && (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) sense[1] == SENSE_DRIVE_ONLINE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) sense[1] == SENSE_BEGINNING_OF_TAPE + SENSE_WRITE_MODE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) )) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) switch (request->op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * sense[0] == SENSE_DATA_CHECK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * sense[1] == SENSE_DRIVE_ONLINE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * sense[3] == 0x36 (End Of Data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * Further seeks might return a 'Volume Fenced'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) case TO_FSF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) case TO_FSB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /* Trying to seek beyond end of recorded area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return tape_34xx_erp_failed(request, -ENOSPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) case TO_BSB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return tape_34xx_erp_retry(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * sense[0] == SENSE_DATA_CHECK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * sense[1] == SENSE_DRIVE_ONLINE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * sense[3] == 0x36 (End Of Data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) case TO_LBL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) /* Block could not be located. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) tape_34xx_delete_sbid_from(device, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) case TO_RFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /* Read beyond end of recorded area -> 0 bytes read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return tape_34xx_erp_failed(request, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * sense[0] == SENSE_EQUIPMENT_CHECK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * sense[1] == SENSE_DRIVE_ONLINE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * sense[3] == 0x38 (Physical End Of Volume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) case TO_WRI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /* Writing at physical end of volume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return tape_34xx_erp_failed(request, -ENOSPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return tape_34xx_erp_failed(request, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /* Sensing special bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (sense[0] & SENSE_BUS_OUT_CHECK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return tape_34xx_erp_retry(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (sense[0] & SENSE_DATA_CHECK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * hardware failure, damaged tape or improper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * operating conditions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) switch (sense[3]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) case 0x23:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) /* a read data check occurred */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if ((sense[2] & SENSE_TAPE_SYNC_MODE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) inhibit_cu_recovery)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) // data check is not permanent, may be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) // recovered. We always use async-mode with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) // cu-recovery, so this should *never* happen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return tape_34xx_erp_bug(device, request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) irb, -4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /* data check is permanent, CU recovery has failed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) dev_warn (&device->cdev->dev, "A read error occurred "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) "that cannot be recovered\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) case 0x25:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) // a write data check occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if ((sense[2] & SENSE_TAPE_SYNC_MODE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) inhibit_cu_recovery)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) // data check is not permanent, may be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) // recovered. We always use async-mode with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) // cu-recovery, so this should *never* happen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return tape_34xx_erp_bug(device, request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) irb, -5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) // data check is permanent, cu-recovery has failed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) dev_warn (&device->cdev->dev, "A write error on the "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) "tape cannot be recovered\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) case 0x26:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /* Data Check (read opposite) occurred. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return tape_34xx_erp_read_opposite(device, request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) case 0x28:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /* ID-Mark at tape start couldn't be written */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) dev_warn (&device->cdev->dev, "Writing the ID-mark "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) "failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) case 0x31:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /* Tape void. Tried to read beyond end of device. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) dev_warn (&device->cdev->dev, "Reading the tape beyond"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) " the end of the recorded area failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) return tape_34xx_erp_failed(request, -ENOSPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) case 0x41:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /* Record sequence error. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) dev_warn (&device->cdev->dev, "The tape contains an "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) "incorrect block ID sequence\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /* all data checks for 3480 should result in one of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) * the above erpa-codes. For 3490, other data-check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) * conditions do exist. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (device->cdev->id.driver_info == tape_3480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return tape_34xx_erp_bug(device, request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) irb, -6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (sense[0] & SENSE_OVERRUN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return tape_34xx_erp_overrun(device, request, irb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (sense[1] & SENSE_RECORD_SEQUENCE_ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) return tape_34xx_erp_sequence(device, request, irb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /* Sensing erpa codes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) switch (sense[3]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) case 0x00:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) /* Unit check with erpa code 0. Report and ignore. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return TAPE_IO_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) case 0x21:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * Data streaming not operational. CU will switch to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * interlock mode. Reissue the command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return tape_34xx_erp_retry(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) case 0x22:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * Path equipment check. Might be drive adapter error, buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * error on the lower interface, internal path not usable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * or error during cartridge load.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) dev_warn (&device->cdev->dev, "A path equipment check occurred"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) " for the tape device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) case 0x24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) * Load display check. Load display was command was issued,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * but the drive is displaying a drive check message. Can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) * be threated as "device end".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return tape_34xx_erp_succeeded(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) case 0x27:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) * Command reject. May indicate illegal channel program or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) * buffer over/underrun. Since all channel programs are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * issued by this driver and ought be correct, we assume a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * over/underrun situation and retry the channel program.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) return tape_34xx_erp_retry(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) case 0x29:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) * Function incompatible. Either the tape is idrc compressed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * but the hardware isn't capable to do idrc, or a perform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) * subsystem func is issued and the CU is not on-line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) case 0x2a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) * Unsolicited environmental data. An internal counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) * overflows, we can ignore this and reissue the cmd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return tape_34xx_erp_retry(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) case 0x2b:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) * Environmental data present. Indicates either unload
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) * completed ok or read buffered log command completed ok.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (request->op == TO_RUN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) /* Rewind unload completed ok. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) tape_med_state_set(device, MS_UNLOADED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return tape_34xx_erp_succeeded(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /* tape_34xx doesn't use read buffered log commands. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return tape_34xx_erp_bug(device, request, irb, sense[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) case 0x2c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * Permanent equipment check. CU has tried recovery, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * did not succeed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) case 0x2d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) /* Data security erase failure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (request->op == TO_DSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) /* Data security erase failure, but no such command issued. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return tape_34xx_erp_bug(device, request, irb, sense[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) case 0x2e:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) * Not capable. This indicates either that the drive fails
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) * reading the format id mark or that that format specified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * is not supported by the drive.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) dev_warn (&device->cdev->dev, "The tape unit cannot process "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) "the tape format\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return tape_34xx_erp_failed(request, -EMEDIUMTYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) case 0x30:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) /* The medium is write protected. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) dev_warn (&device->cdev->dev, "The tape medium is write-"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) "protected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return tape_34xx_erp_failed(request, -EACCES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) case 0x32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) // Tension loss. We cannot recover this, it's an I/O error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) dev_warn (&device->cdev->dev, "The tape does not have the "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) "required tape tension\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) case 0x33:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * Load Failure. The cartridge was not inserted correctly or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) * the tape is not threaded correctly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) dev_warn (&device->cdev->dev, "The tape unit failed to load"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) " the cartridge\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) tape_34xx_delete_sbid_from(device, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) case 0x34:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * Unload failure. The drive cannot maintain tape tension
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * and control tape movement during an unload operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) dev_warn (&device->cdev->dev, "Automatic unloading of the tape"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) " cartridge failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (request->op == TO_RUN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return tape_34xx_erp_bug(device, request, irb, sense[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) case 0x35:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) * Drive equipment check. One of the following:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * - cu cannot recover from a drive detected error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) * - a check code message is shown on drive display
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) * - the cartridge loader does not respond correctly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) * - a failure occurs during an index, load, or unload cycle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) dev_warn (&device->cdev->dev, "An equipment check has occurred"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) " on the tape unit\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) case 0x36:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (device->cdev->id.driver_info == tape_3490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) /* End of data. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /* This erpa is reserved for 3480 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return tape_34xx_erp_bug(device, request, irb, sense[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) case 0x37:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) * Tape length error. The tape is shorter than reported in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * the beginning-of-tape data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) dev_warn (&device->cdev->dev, "The tape information states an"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) " incorrect length\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) case 0x38:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * Physical end of tape. A read/write operation reached
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * the physical end of tape.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (request->op==TO_WRI ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) request->op==TO_DSE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) request->op==TO_WTM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return tape_34xx_erp_failed(request, -ENOSPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) case 0x39:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /* Backward at Beginning of tape. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) case 0x3a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) /* Drive switched to not ready. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) dev_warn (&device->cdev->dev, "The tape unit is not ready\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) case 0x3b:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) /* Manual rewind or unload. This causes an I/O error. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) dev_warn (&device->cdev->dev, "The tape medium has been "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) "rewound or unloaded manually\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) tape_34xx_delete_sbid_from(device, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) case 0x42:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) * Degraded mode. A condition that can cause degraded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * performance is detected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) dev_warn (&device->cdev->dev, "The tape subsystem is running "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) "in degraded mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return tape_34xx_erp_retry(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) case 0x43:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) /* Drive not ready. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) tape_34xx_delete_sbid_from(device, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) tape_med_state_set(device, MS_UNLOADED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) /* Some commands commands are successful even in this case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (sense[1] & SENSE_DRIVE_ONLINE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) switch(request->op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) case TO_ASSIGN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) case TO_UNASSIGN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) case TO_DIS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) case TO_NOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) return tape_34xx_done(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) return tape_34xx_erp_failed(request, -ENOMEDIUM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) case 0x44:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) /* Locate Block unsuccessful. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (request->op != TO_BLOCK && request->op != TO_LBL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) /* No locate block was issued. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return tape_34xx_erp_bug(device, request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) irb, sense[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) case 0x45:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) /* The drive is assigned to a different channel path. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) dev_warn (&device->cdev->dev, "The tape unit is already "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) "assigned\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) case 0x46:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * Drive not on-line. Drive may be switched offline,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * the power supply may be switched off or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * the drive address may not be set correctly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) dev_warn (&device->cdev->dev, "The tape unit is not online\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) case 0x47:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) /* Volume fenced. CU reports volume integrity is lost. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) dev_warn (&device->cdev->dev, "The control unit has fenced "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) "access to the tape volume\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) tape_34xx_delete_sbid_from(device, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) case 0x48:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) /* Log sense data and retry request. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return tape_34xx_erp_retry(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) case 0x49:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) /* Bus out check. A parity check error on the bus was found. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) dev_warn (&device->cdev->dev, "A parity error occurred on the "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) "tape bus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) case 0x4a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) /* Control unit erp failed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) dev_warn (&device->cdev->dev, "I/O error recovery failed on "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) "the tape control unit\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) case 0x4b:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * CU and drive incompatible. The drive requests micro-program
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * patches, which are not available on the CU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) dev_warn (&device->cdev->dev, "The tape unit requires a "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) "firmware update\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) case 0x4c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) * Recovered Check-One failure. Cu develops a hardware error,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) * but is able to recover.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return tape_34xx_erp_retry(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) case 0x4d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (device->cdev->id.driver_info == tape_3490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * Resetting event received. Since the driver does
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * not support resetting event recovery (which has to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * be handled by the I/O Layer), retry our command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return tape_34xx_erp_retry(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) /* This erpa is reserved for 3480. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return tape_34xx_erp_bug(device, request, irb, sense[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) case 0x4e:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (device->cdev->id.driver_info == tape_3490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) * Maximum block size exceeded. This indicates, that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) * the block to be written is larger than allowed for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) * buffered mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) dev_warn (&device->cdev->dev, "The maximum block size"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) " for buffered mode is exceeded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) return tape_34xx_erp_failed(request, -ENOBUFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) /* This erpa is reserved for 3480. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) return tape_34xx_erp_bug(device, request, irb, sense[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) case 0x50:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) * Read buffered log (Overflow). CU is running in extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) * buffered log mode, and a counter overflows. This should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) * never happen, since we're never running in extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) * buffered log mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) return tape_34xx_erp_retry(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) case 0x51:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) * Read buffered log (EOV). EOF processing occurs while the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) * CU is in extended buffered log mode. This should never
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) * happen, since we're never running in extended buffered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) * log mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) return tape_34xx_erp_retry(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) case 0x52:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) /* End of Volume complete. Rewind unload completed ok. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (request->op == TO_RUN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) tape_med_state_set(device, MS_UNLOADED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) tape_34xx_delete_sbid_from(device, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return tape_34xx_erp_succeeded(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) return tape_34xx_erp_bug(device, request, irb, sense[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) case 0x53:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) /* Global command intercept. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) return tape_34xx_erp_retry(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) case 0x54:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /* Channel interface recovery (temporary). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) return tape_34xx_erp_retry(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) case 0x55:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) /* Channel interface recovery (permanent). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) dev_warn (&device->cdev->dev, "A channel interface error cannot be"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) " recovered\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) case 0x56:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) /* Channel protocol error. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) dev_warn (&device->cdev->dev, "A channel protocol error "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) "occurred\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) case 0x57:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) * 3480: Attention intercept.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) * 3490: Global status intercept.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return tape_34xx_erp_retry(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) case 0x5a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) * Tape length incompatible. The tape inserted is too long,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) * which could cause damage to the tape or the drive.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) dev_warn (&device->cdev->dev, "The tape unit does not support "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) "the tape length\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) case 0x5b:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) /* Format 3480 XF incompatible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (sense[1] & SENSE_BEGINNING_OF_TAPE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) /* The tape will get overwritten. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) return tape_34xx_erp_retry(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) dev_warn (&device->cdev->dev, "The tape unit does not support"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) " format 3480 XF\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) case 0x5c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /* Format 3480-2 XF incompatible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) dev_warn (&device->cdev->dev, "The tape unit does not support tape "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) "format 3480-2 XF\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) return tape_34xx_erp_failed(request, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) case 0x5d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) /* Tape length violation. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) dev_warn (&device->cdev->dev, "The tape unit does not support"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) " the current tape length\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) return tape_34xx_erp_failed(request, -EMEDIUMTYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) case 0x5e:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) /* Compaction algorithm incompatible. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) dev_warn (&device->cdev->dev, "The tape unit does not support"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) " the compaction algorithm\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) return tape_34xx_erp_failed(request, -EMEDIUMTYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) /* The following erpas should have been covered earlier. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) case 0x23: /* Read data check. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) case 0x25: /* Write data check. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) case 0x26: /* Data check (read opposite). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) case 0x28: /* Write id mark check. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) case 0x31: /* Tape void. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) case 0x40: /* Overrun error. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) case 0x41: /* Record sequence error. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) /* All other erpas are reserved for future use. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) return tape_34xx_erp_bug(device, request, irb, sense[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) * 3480/3490 interrupt handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) tape_34xx_irq(struct tape_device *device, struct tape_request *request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) struct irb *irb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if (request == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) return tape_34xx_unsolicited_irq(device, irb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if ((irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) (request->op == TO_WRI)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) /* Write at end of volume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return tape_34xx_erp_failed(request, -ENOSPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) return tape_34xx_unit_check(device, request, irb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * A unit exception occurs on skipping over a tapemark block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (request->op == TO_BSB || request->op == TO_FSB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) request->rescnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) DBF_EVENT(5, "Unit Exception!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return tape_34xx_done(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) DBF_EVENT(6, "xunknownirq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) tape_dump_sense_dbf(device, request, irb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) return TAPE_IO_STOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) * ioctl_overload
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) tape_34xx_ioctl(struct tape_device *device, unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (cmd == TAPE390_DISPLAY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) struct display_struct disp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) if (copy_from_user(&disp, (char __user *) arg, sizeof(disp)) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) return tape_std_display(device, &disp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) tape_34xx_append_new_sbid(struct tape_34xx_block_id bid, struct list_head *l)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) struct tape_34xx_sbid * new_sbid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) new_sbid = kmalloc(sizeof(*new_sbid), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if (!new_sbid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) new_sbid->bid = bid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) list_add(&new_sbid->list, l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) * Build up the search block ID list. The block ID consists of a logical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) * block number and a hardware specific part. The hardware specific part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * helps the tape drive to speed up searching for a specific block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) tape_34xx_add_sbid(struct tape_device *device, struct tape_34xx_block_id bid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) struct list_head * sbid_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) struct tape_34xx_sbid * sbid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) struct list_head * l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) * immediately return if there is no list at all or the block to add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) * is located in segment 1 of wrap 0 because this position is used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) * if no hardware position data is supplied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) sbid_list = (struct list_head *) device->discdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (!sbid_list || (bid.segment < 2 && bid.wrap == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) * Search the position where to insert the new entry. Hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) * acceleration uses only the segment and wrap number. So we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) * need only one entry for a specific wrap/segment combination.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) * If there is a block with a lower number but the same hard-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) * ware position data we just update the block number in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) * existing entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) list_for_each(l, sbid_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) sbid = list_entry(l, struct tape_34xx_sbid, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) (sbid->bid.segment == bid.segment) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) (sbid->bid.wrap == bid.wrap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (bid.block < sbid->bid.block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) sbid->bid = bid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) else return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) /* Sort in according to logical block number. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) if (bid.block < sbid->bid.block) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) tape_34xx_append_new_sbid(bid, l->prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) /* List empty or new block bigger than last entry. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if (l == sbid_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) tape_34xx_append_new_sbid(bid, l->prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) DBF_LH(4, "Current list is:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) list_for_each(l, sbid_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) sbid = list_entry(l, struct tape_34xx_sbid, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) DBF_LH(4, "%d:%03d@%05d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) sbid->bid.wrap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) sbid->bid.segment,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) sbid->bid.block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) * Delete all entries from the search block ID list that belong to tape blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) * equal or higher than the given number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) tape_34xx_delete_sbid_from(struct tape_device *device, int from)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) struct list_head * sbid_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) struct tape_34xx_sbid * sbid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) struct list_head * l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) struct list_head * n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) sbid_list = (struct list_head *) device->discdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) if (!sbid_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) list_for_each_safe(l, n, sbid_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) sbid = list_entry(l, struct tape_34xx_sbid, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (sbid->bid.block >= from) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) DBF_LH(4, "Delete sbid %d:%03d@%05d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) sbid->bid.wrap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) sbid->bid.segment,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) sbid->bid.block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) list_del(l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) kfree(sbid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) * Merge hardware position data into a block id.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) tape_34xx_merge_sbid(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) struct tape_device * device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) struct tape_34xx_block_id * bid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) struct tape_34xx_sbid * sbid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) struct tape_34xx_sbid * sbid_to_use;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) struct list_head * sbid_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) struct list_head * l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) sbid_list = (struct list_head *) device->discdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) bid->wrap = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) bid->segment = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (!sbid_list || list_empty(sbid_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) sbid_to_use = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) list_for_each(l, sbid_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) sbid = list_entry(l, struct tape_34xx_sbid, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (sbid->bid.block >= bid->block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) sbid_to_use = sbid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (sbid_to_use) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) bid->wrap = sbid_to_use->bid.wrap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) bid->segment = sbid_to_use->bid.segment;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) DBF_LH(4, "Use %d:%03d@%05d for %05d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) sbid_to_use->bid.wrap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) sbid_to_use->bid.segment,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) sbid_to_use->bid.block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) bid->block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) tape_34xx_setup_device(struct tape_device * device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) struct list_head * discdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) DBF_EVENT(6, "34xx device setup\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if ((rc = tape_std_assign(device)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) if ((rc = tape_34xx_medium_sense(device)) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) DBF_LH(3, "34xx medium sense returned %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) discdata = kmalloc(sizeof(struct list_head), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) if (discdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) INIT_LIST_HEAD(discdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) device->discdata = discdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) tape_34xx_cleanup_device(struct tape_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) tape_std_unassign(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) if (device->discdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) tape_34xx_delete_sbid_from(device, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) kfree(device->discdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) device->discdata = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) * MTTELL: Tell block. Return the number of block relative to current file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) tape_34xx_mttell(struct tape_device *device, int mt_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) struct tape_34xx_block_id cbid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) struct tape_34xx_block_id dbid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) } __attribute__ ((packed)) block_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) rc = tape_std_read_block_id(device, (__u64 *) &block_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) tape_34xx_add_sbid(device, block_id.cbid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) return block_id.cbid.block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) * MTSEEK: seek to the specified block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) tape_34xx_mtseek(struct tape_device *device, int mt_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) struct tape_request *request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) struct tape_34xx_block_id * bid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if (mt_count > 0x3fffff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) DBF_EXCEPTION(6, "xsee parm\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) request = tape_alloc_request(3, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) if (IS_ERR(request))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) return PTR_ERR(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) /* setup ccws */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) request->op = TO_LBL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) bid = (struct tape_34xx_block_id *) request->cpdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) bid->format = (*device->modeset_byte & 0x08) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) TAPE34XX_FMT_3480_XF : TAPE34XX_FMT_3480;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) bid->block = mt_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) tape_34xx_merge_sbid(device, bid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) tape_ccw_cc(request->cpaddr + 1, LOCATE, 4, request->cpdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) /* execute it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) return tape_do_io_free(device, request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) * List of 3480/3490 magnetic tape commands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) static tape_mtop_fn tape_34xx_mtop[TAPE_NR_MTOPS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) [MTRESET] = tape_std_mtreset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) [MTFSF] = tape_std_mtfsf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) [MTBSF] = tape_std_mtbsf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) [MTFSR] = tape_std_mtfsr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) [MTBSR] = tape_std_mtbsr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) [MTWEOF] = tape_std_mtweof,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) [MTREW] = tape_std_mtrew,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) [MTOFFL] = tape_std_mtoffl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) [MTNOP] = tape_std_mtnop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) [MTRETEN] = tape_std_mtreten,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) [MTBSFM] = tape_std_mtbsfm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) [MTFSFM] = tape_std_mtfsfm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) [MTEOM] = tape_std_mteom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) [MTERASE] = tape_std_mterase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) [MTRAS1] = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) [MTRAS2] = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) [MTRAS3] = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) [MTSETBLK] = tape_std_mtsetblk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) [MTSETDENSITY] = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) [MTSEEK] = tape_34xx_mtseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) [MTTELL] = tape_34xx_mttell,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) [MTSETDRVBUFFER] = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) [MTFSS] = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) [MTBSS] = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) [MTWSM] = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) [MTLOCK] = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) [MTUNLOCK] = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) [MTLOAD] = tape_std_mtload,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) [MTUNLOAD] = tape_std_mtunload,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) [MTCOMPRESSION] = tape_std_mtcompression,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) [MTSETPART] = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) [MTMKPART] = NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) * Tape discipline structure for 3480 and 3490.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) static struct tape_discipline tape_discipline_34xx = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) .setup_device = tape_34xx_setup_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) .cleanup_device = tape_34xx_cleanup_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) .process_eov = tape_std_process_eov,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) .irq = tape_34xx_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) .read_block = tape_std_read_block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) .write_block = tape_std_write_block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) .ioctl_fn = tape_34xx_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) .mtop_array = tape_34xx_mtop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) static struct ccw_device_id tape_34xx_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) { CCW_DEVICE_DEVTYPE(0x3480, 0, 0x3480, 0), .driver_info = tape_3480},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) { CCW_DEVICE_DEVTYPE(0x3490, 0, 0x3490, 0), .driver_info = tape_3490},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) { /* end of list */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) tape_34xx_online(struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) return tape_generic_online(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) dev_get_drvdata(&cdev->dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) &tape_discipline_34xx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) static struct ccw_driver tape_34xx_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) .name = "tape_34xx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) .ids = tape_34xx_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) .probe = tape_generic_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) .remove = tape_generic_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) .set_online = tape_34xx_online,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) .set_offline = tape_generic_offline,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) .freeze = tape_generic_pm_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) .int_class = IRQIO_TAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) tape_34xx_init (void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) TAPE_DBF_AREA = debug_register ( "tape_34xx", 2, 2, 4*sizeof(long));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) debug_register_view(TAPE_DBF_AREA, &debug_sprintf_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) #ifdef DBF_LIKE_HELL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) debug_set_level(TAPE_DBF_AREA, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) DBF_EVENT(3, "34xx init\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) /* Register driver for 3480/3490 tapes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) rc = ccw_driver_register(&tape_34xx_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) DBF_EVENT(3, "34xx init failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) DBF_EVENT(3, "34xx registered\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) tape_34xx_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) ccw_driver_unregister(&tape_34xx_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) debug_unregister(TAPE_DBF_AREA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) MODULE_DEVICE_TABLE(ccw, tape_34xx_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) MODULE_AUTHOR("(C) 2001-2002 IBM Deutschland Entwicklung GmbH");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) MODULE_DESCRIPTION("Linux on zSeries channel attached 3480 tape device driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) module_init(tape_34xx_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) module_exit(tape_34xx_exit);