1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Implementation of "scsi_vhci_f_tape" tape failover_ops. 29 * 30 * This file was historically meant for only tape implementation. It has 31 * been extended to manage SUN "supported" tape controllers. The supported 32 * VID/PID shall be listed in the tape_dev_table. 33 */ 34 35 #include <sys/conf.h> 36 #include <sys/file.h> 37 #include <sys/ddi.h> 38 #include <sys/sunddi.h> 39 #include <sys/scsi/scsi.h> 40 #include <sys/scsi/adapters/scsi_vhci.h> 41 42 /* Supported device table entries. */ 43 static char *tape_dev_table[] = { 44 /* " 111111" */ 45 /* "012345670123456789012345" */ 46 /* "|-VID--||-----PID------|" */ 47 "IBM ULTRIUM-TD3", 48 "IBM ULTRIUM-TD4", 49 NULL 50 }; 51 52 /* Failover module plumbing. */ 53 SCSI_FAILOVER_OP("f_tape", tape); 54 55 /* ARGSUSED */ 56 static int 57 tape_device_probe(struct scsi_device *sd, struct scsi_inquiry *inquiry, 58 void **ctpriv) 59 { 60 int i; 61 int rval = SFO_DEVICE_PROBE_PHCI; 62 63 VHCI_DEBUG(6, (CE_NOTE, NULL, "!tape_device_probe: inquiry string %s\n", 64 inquiry->inq_vid)); 65 /* 66 * See if this a device type that we want to care about. 67 */ 68 switch (inquiry->inq_dtype & DTYPE_MASK) { 69 case DTYPE_SEQUENTIAL: 70 break; 71 case DTYPE_CHANGER: 72 rval = SFO_DEVICE_PROBE_VHCI; 73 goto done; 74 default: 75 /* 76 * Not interested. 77 */ 78 return (rval); 79 } 80 81 /* 82 * If it reports that it supports tpgs and it got here it may have 83 * failed the tpgs commands. It might or might not support dual port 84 * but we'll go with it. 85 */ 86 if (inquiry->inq_tpgs) { 87 VHCI_DEBUG(6, (CE_NOTE, NULL, "!has tpgs bits: %s\n", 88 inquiry->inq_vid)); 89 rval = SFO_DEVICE_PROBE_VHCI; 90 } else if (inquiry->inq_dualp) { 91 /* 92 * Looks like it claims to have more then one port. 93 */ 94 VHCI_DEBUG(6, (CE_NOTE, NULL, "!has dual port bits: %s\n", 95 inquiry->inq_vid)); 96 rval = SFO_DEVICE_PROBE_VHCI; 97 } else { 98 99 /* 100 * See if this device is on the list. 101 */ 102 for (i = 0; tape_dev_table[i]; i++) { 103 104 if (strncmp(inquiry->inq_vid, tape_dev_table[i], 105 strlen(tape_dev_table[i])) == 0) { 106 VHCI_DEBUG(6, (CE_NOTE, NULL, 107 "!was on the list: %s\n", 108 inquiry->inq_vid)); 109 rval = SFO_DEVICE_PROBE_VHCI; 110 break; 111 } 112 } 113 } 114 done: 115 if (rval == SFO_DEVICE_PROBE_VHCI) { 116 /* 117 * Policy only applies to 'client' probe, not 118 * vhci_is_dev_supported() pHCI probe. Detect difference 119 * based on ctpriv. 120 */ 121 if (ctpriv && 122 (mdi_set_lb_policy(sd->sd_dev, LOAD_BALANCE_NONE) != 123 MDI_SUCCESS)) { 124 VHCI_DEBUG(6, (CE_NOTE, NULL, "!fail load balance none" 125 ": %s\n", inquiry->inq_vid)); 126 return (SFO_DEVICE_PROBE_PHCI); 127 } 128 129 } 130 return (rval); 131 } 132 133 /* ARGSUSED */ 134 static void 135 tape_device_unprobe(struct scsi_device *sd, void *ctpriv) 136 { 137 /* 138 * NO OP for tape. 139 */ 140 141 } 142 143 /* ARGSUSED */ 144 static int 145 tape_path_activate(struct scsi_device *sd, char *pathclass, void *ctpriv) 146 { 147 return (0); 148 } 149 150 /* ARGSUSED */ 151 static int 152 tape_path_deactivate(struct scsi_device *sd, char *pathclass, void *ctpriv) 153 { 154 return (0); 155 } 156 157 /* ARGSUSED */ 158 static int 159 tape_path_get_opinfo(struct scsi_device *sd, struct scsi_path_opinfo *opinfo, 160 void *ctpriv) 161 { 162 opinfo->opinfo_rev = OPINFO_REV; 163 (void) strcpy(opinfo->opinfo_path_attr, PCLASS_PRIMARY); 164 opinfo->opinfo_path_state = SCSI_PATH_ACTIVE; 165 opinfo->opinfo_pswtch_best = 0; /* N/A */ 166 opinfo->opinfo_pswtch_worst = 0; /* N/A */ 167 opinfo->opinfo_xlf_capable = 0; 168 opinfo->opinfo_mode = SCSI_NO_FAILOVER; 169 opinfo->opinfo_preferred = 1; 170 171 return (0); 172 } 173 174 /* ARGSUSED */ 175 static int 176 tape_path_ping(struct scsi_device *sd, void *ctpriv) 177 { 178 return (1); 179 } 180 181 /* ARGSUSED */ 182 static int 183 tape_analyze_sense(struct scsi_device *sd, uint8_t *sense, 184 void *ctpriv) 185 { 186 uint8_t skey, asc, ascq; 187 188 skey = scsi_sense_key(sense); 189 asc = scsi_sense_asc(sense); 190 ascq = scsi_sense_ascq(sense); 191 192 if (skey == KEY_ABORTED_COMMAND && 193 asc == 0x4b && 194 ascq == 0x83) { 195 return (SCSI_SENSE_INACTIVE); 196 } 197 if (skey == KEY_NOT_READY && 198 asc == 0x4 && 199 ascq == 0x1) { 200 return (SCSI_SENSE_NOT_READY); 201 } 202 return (SCSI_SENSE_NOFAILOVER); 203 } 204 205 /* ARGSUSED */ 206 static int 207 tape_pathclass_next(char *cur, char **nxt, void *ctpriv) 208 { 209 if (cur == NULL) { 210 *nxt = PCLASS_PRIMARY; 211 return (0); 212 } else if (strcmp(cur, PCLASS_PRIMARY) == 0) { 213 return (ENOENT); 214 } 215 return (EINVAL); 216 } 217