#include <sys/conf.h>
#include <sys/file.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/scsi/scsi.h>
#include <sys/scsi/adapters/scsi_vhci.h>
static char *tape_dev_table[] = {
"IBM ULTRIUM-TD3",
"IBM ULTRIUM-TD4",
NULL
};
SCSI_FAILOVER_OP("f_tape", tape);
static int
tape_device_probe(struct scsi_device *sd, struct scsi_inquiry *inquiry,
void **ctpriv)
{
int i;
int rval = SFO_DEVICE_PROBE_PHCI;
VHCI_DEBUG(6, (CE_NOTE, NULL, "!tape_device_probe: inquiry string %s\n",
inquiry->inq_vid));
switch (inquiry->inq_dtype & DTYPE_MASK) {
case DTYPE_SEQUENTIAL:
break;
case DTYPE_CHANGER:
rval = SFO_DEVICE_PROBE_VHCI;
goto done;
default:
return (rval);
}
if (inquiry->inq_tpgs) {
VHCI_DEBUG(6, (CE_NOTE, NULL, "!has tpgs bits: %s\n",
inquiry->inq_vid));
rval = SFO_DEVICE_PROBE_VHCI;
} else if (inquiry->inq_dualp) {
VHCI_DEBUG(6, (CE_NOTE, NULL, "!has dual port bits: %s\n",
inquiry->inq_vid));
rval = SFO_DEVICE_PROBE_VHCI;
} else {
for (i = 0; tape_dev_table[i]; i++) {
if (strncmp(inquiry->inq_vid, tape_dev_table[i],
strlen(tape_dev_table[i])) == 0) {
VHCI_DEBUG(6, (CE_NOTE, NULL,
"!was on the list: %s\n",
inquiry->inq_vid));
rval = SFO_DEVICE_PROBE_VHCI;
break;
}
}
}
done:
if (rval == SFO_DEVICE_PROBE_VHCI) {
if (ctpriv &&
(mdi_set_lb_policy(sd->sd_dev, LOAD_BALANCE_NONE) !=
MDI_SUCCESS)) {
VHCI_DEBUG(6, (CE_NOTE, NULL, "!fail load balance none"
": %s\n", inquiry->inq_vid));
return (SFO_DEVICE_PROBE_PHCI);
}
}
return (rval);
}
static void
tape_device_unprobe(struct scsi_device *sd, void *ctpriv)
{
}
static int
tape_path_activate(struct scsi_device *sd, char *pathclass, void *ctpriv)
{
return (0);
}
static int
tape_path_deactivate(struct scsi_device *sd, char *pathclass, void *ctpriv)
{
return (0);
}
static int
tape_path_get_opinfo(struct scsi_device *sd, struct scsi_path_opinfo *opinfo,
void *ctpriv)
{
opinfo->opinfo_rev = OPINFO_REV;
(void) strcpy(opinfo->opinfo_path_attr, PCLASS_PRIMARY);
opinfo->opinfo_path_state = SCSI_PATH_ACTIVE;
opinfo->opinfo_pswtch_best = 0;
opinfo->opinfo_pswtch_worst = 0;
opinfo->opinfo_xlf_capable = 0;
opinfo->opinfo_mode = SCSI_NO_FAILOVER;
opinfo->opinfo_preferred = 1;
return (0);
}
static int
tape_path_ping(struct scsi_device *sd, void *ctpriv)
{
return (1);
}
static int
tape_analyze_sense(struct scsi_device *sd, uint8_t *sense,
void *ctpriv)
{
uint8_t skey, asc, ascq;
skey = scsi_sense_key(sense);
asc = scsi_sense_asc(sense);
ascq = scsi_sense_ascq(sense);
if (skey == KEY_ABORTED_COMMAND &&
asc == 0x4b &&
ascq == 0x83) {
return (SCSI_SENSE_INACTIVE);
}
if (skey == KEY_NOT_READY &&
asc == 0x4 &&
ascq == 0x1) {
return (SCSI_SENSE_NOT_READY);
}
return (SCSI_SENSE_NOFAILOVER);
}
static int
tape_pathclass_next(char *cur, char **nxt, void *ctpriv)
{
if (cur == NULL) {
*nxt = PCLASS_PRIMARY;
return (0);
} else if (strcmp(cur, PCLASS_PRIMARY) == 0) {
return (ENOENT);
}
return (EINVAL);
}