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