FreeBSD/sys/cam/scsi/scsi_ch.c
/*
 * Copy an element status descriptor to a user-mode
 * changer_element_status structure.
 */
Copy an element status descriptor to a user-mode
changer_element_status structure.
Copy an element status descriptor to a user - mode changer_element_status structure .
static void
copy_element_status(struct ch_softc *softc,
		    u_int16_t flags,
		    struct read_element_status_descriptor *desc,
		    struct changer_element_status *ces,
		    int scsi_version)
{
	u_int16_t eaddr = scsi_2btoul(desc->eaddr);
	u_int16_t et;
	struct volume_tag *pvol_tag = NULL, *avol_tag = NULL;
	struct read_element_status_device_id *devid = NULL;
	ces->ces_int_addr = eaddr;
	for (et = CHET_MT; et <= CHET_DT; et++) {
		if ((softc->sc_firsts[et] <= eaddr)
		    && ((softc->sc_firsts[et] + softc->sc_counts[et])
			> eaddr)) {
			ces->ces_addr = eaddr - softc->sc_firsts[et];
			ces->ces_type = et;
			break;
		}
	}
	ces->ces_flags = desc->flags1;
	ces->ces_sensecode = desc->sense_code;
	ces->ces_sensequal = desc->sense_qual;
	if (desc->flags2 & READ_ELEMENT_STATUS_INVERT)
		ces->ces_flags |= CES_INVERT;
	if (desc->flags2 & READ_ELEMENT_STATUS_SVALID) {
		eaddr = scsi_2btoul(desc->ssea);
		for (et = CHET_MT; et <= CHET_DT; et++) {
			if ((softc->sc_firsts[et] <= eaddr)
			    && ((softc->sc_firsts[et] + softc->sc_counts[et])
				> eaddr)) {
				ces->ces_source_addr =
					eaddr - softc->sc_firsts[et];
				ces->ces_source_type = et;
				ces->ces_flags |= CES_SOURCE_VALID;
				break;
			}
		}
		if (!(ces->ces_flags & CES_SOURCE_VALID))
			printf("ch: warning: could not map element source "
			       "address %ud to a valid element type\n",
			       eaddr);
	}
	if (flags & READ_ELEMENT_STATUS_PVOLTAG)
		pvol_tag = &desc->voltag_devid.pvoltag;
	if (flags & READ_ELEMENT_STATUS_AVOLTAG)
		avol_tag = (flags & READ_ELEMENT_STATUS_PVOLTAG) ?
		    &desc->voltag_devid.voltag[1] :&desc->voltag_devid.pvoltag;
	if (scsi_version >= SCSI_REV_SPC) {
		if ((flags & READ_ELEMENT_STATUS_PVOLTAG) ^
		    (flags & READ_ELEMENT_STATUS_AVOLTAG))
			devid = &desc->voltag_devid.pvol_and_devid.devid;
		else if (!(flags & READ_ELEMENT_STATUS_PVOLTAG) &&
			 !(flags & READ_ELEMENT_STATUS_AVOLTAG))
			devid = &desc->voltag_devid.devid;
		else 
			devid = &desc->voltag_devid.vol_tags_and_devid.devid;
	}
	if (pvol_tag)
		copy_voltag(&(ces->ces_pvoltag), pvol_tag);
	if (avol_tag)
		copy_voltag(&(ces->ces_pvoltag), avol_tag);
	if (devid != NULL) {
		if (devid->designator_length > 0) {
			bcopy((void *)devid->designator,
			      (void *)ces->ces_designator,
			      devid->designator_length);
			ces->ces_designator_length = devid->designator_length;
			ces->ces_designator[devid->designator_length]= '\0';
		}
		if (devid->piv_assoc_designator_type &
		    READ_ELEMENT_STATUS_PIV_SET) {
			ces->ces_flags |= CES_PIV;
			ces->ces_protocol_id =
			    READ_ELEMENT_STATUS_PROTOCOL_ID(
			    devid->prot_code_set);
		}
		ces->ces_code_set =
		    READ_ELEMENT_STATUS_CODE_SET(devid->prot_code_set);
		ces->ces_assoc = READ_ELEMENT_STATUS_ASSOCIATION(
		    devid->piv_assoc_designator_type);
		ces->ces_designator_type = READ_ELEMENT_STATUS_DESIGNATOR_TYPE(
		    devid->piv_assoc_designator_type);
	} else if (scsi_version > SCSI_REV_2) {
		ces->ces_designator_length = 0;
		ces->ces_designator[0] = '\0';
		ces->ces_protocol_id = CES_PROTOCOL_ID_FCP_4;
	}
	if (scsi_version <= SCSI_REV_2) {
		if (desc->dt_or_obsolete.scsi_2.dt_scsi_flags &
		    READ_ELEMENT_STATUS_DT_IDVALID) {
			ces->ces_flags |= CES_SCSIID_VALID;
			ces->ces_scsi_id =
			    desc->dt_or_obsolete.scsi_2.dt_scsi_addr;
		}
		if (desc->dt_or_obsolete.scsi_2.dt_scsi_addr &
		    READ_ELEMENT_STATUS_DT_LUVALID) {
			ces->ces_flags |= CES_LUN_VALID;
			ces->ces_scsi_lun =
			    desc->dt_or_obsolete.scsi_2.dt_scsi_flags &
			    READ_ELEMENT_STATUS_DT_LUNMASK;
		}
	}
}
static void copy_element_status ( struct ch_softc * softc , u_int16_t flags , struct read_element_status_descriptor * desc , struct changer_element_status * ces , int scsi_version ) { u_int16_t eaddr = scsi_2btoul ( desc -> eaddr ) ; u_int16_t et ; struct volume_tag * pvol_tag = NULL , * avol_tag = NULL ; struct read_element_status_device_id * devid = NULL ; ces -> ces_int_addr = eaddr ; for ( et = CHET_MT ; et <= CHET_DT ; et ++ ) { if ( ( softc -> sc_firsts [ et ] <= eaddr ) && ( ( softc -> sc_firsts [ et ] + softc -> sc_counts [ et ] ) > eaddr ) ) { ces -> ces_addr = eaddr - softc -> sc_firsts [ et ] ; ces -> ces_type = et ; break ; } } ces -> ces_flags = desc -> flags1 ; ces -> ces_sensecode = desc -> sense_code ; ces -> ces_sensequal = desc -> sense_qual ; if ( desc -> flags2 & READ_ELEMENT_STATUS_INVERT ) ces -> ces_flags |= CES_INVERT ; if ( desc -> flags2 & READ_ELEMENT_STATUS_SVALID ) { eaddr = scsi_2btoul ( desc -> ssea ) ; for ( et = CHET_MT ; et <= CHET_DT ; et ++ ) { if ( ( softc -> sc_firsts [ et ] <= eaddr ) && ( ( softc -> sc_firsts [ et ] + softc -> sc_counts [ et ] ) > eaddr ) ) { ces -> ces_source_addr = eaddr - softc -> sc_firsts [ et ] ; ces -> ces_source_type = et ; ces -> ces_flags |= CES_SOURCE_VALID ; break ; } } if ( ! ( ces -> ces_flags & CES_SOURCE_VALID ) ) printf ( " " " \n " , eaddr ) ; } if ( flags & READ_ELEMENT_STATUS_PVOLTAG ) pvol_tag = & desc -> voltag_devid . pvoltag ; if ( flags & READ_ELEMENT_STATUS_AVOLTAG ) avol_tag = ( flags & READ_ELEMENT_STATUS_PVOLTAG ) ? & desc -> voltag_devid . voltag [ 1 ] : & desc -> voltag_devid . pvoltag ; if ( scsi_version >= SCSI_REV_SPC ) { if ( ( flags & READ_ELEMENT_STATUS_PVOLTAG ) ^ ( flags & READ_ELEMENT_STATUS_AVOLTAG ) ) devid = & desc -> voltag_devid . pvol_and_devid . devid ; else if ( ! ( flags & READ_ELEMENT_STATUS_PVOLTAG ) && ! ( flags & READ_ELEMENT_STATUS_AVOLTAG ) ) devid = & desc -> voltag_devid . devid ; else devid = & desc -> voltag_devid . vol_tags_and_devid . devid ; } if ( pvol_tag ) copy_voltag ( & ( ces -> ces_pvoltag ) , pvol_tag ) ; if ( avol_tag ) copy_voltag ( & ( ces -> ces_pvoltag ) , avol_tag ) ; if ( devid != NULL ) { if ( devid -> designator_length > 0 ) { bcopy ( ( void * ) devid -> designator , ( void * ) ces -> ces_designator , devid -> designator_length ) ; ces -> ces_designator_length = devid -> designator_length ; ces -> ces_designator [ devid -> designator_length ] = ' \0 ' ; } if ( devid -> piv_assoc_designator_type & READ_ELEMENT_STATUS_PIV_SET ) { ces -> ces_flags |= CES_PIV ; ces -> ces_protocol_id = READ_ELEMENT_STATUS_PROTOCOL_ID ( devid -> prot_code_set ) ; } ces -> ces_code_set = READ_ELEMENT_STATUS_CODE_SET ( devid -> prot_code_set ) ; ces -> ces_assoc = READ_ELEMENT_STATUS_ASSOCIATION ( devid -> piv_assoc_designator_type ) ; ces -> ces_designator_type = READ_ELEMENT_STATUS_DESIGNATOR_TYPE ( devid -> piv_assoc_designator_type ) ; } else if ( scsi_version > SCSI_REV_2 ) { ces -> ces_designator_length = 0 ; ces -> ces_designator [ 0 ] = ' \0 ' ; ces -> ces_protocol_id = CES_PROTOCOL_ID_FCP_4 ; } if ( scsi_version <= SCSI_REV_2 ) { if ( desc -> dt_or_obsolete . scsi_2 . dt_scsi_flags & READ_ELEMENT_STATUS_DT_IDVALID ) { ces -> ces_flags |= CES_SCSIID_VALID ; ces -> ces_scsi_id = desc -> dt_or_obsolete . scsi_2 . dt_scsi_addr ; } if ( desc -> dt_or_obsolete . scsi_2 . dt_scsi_addr & READ_ELEMENT_STATUS_DT_LUVALID ) { ces -> ces_flags |= CES_LUN_VALID ; ces -> ces_scsi_lun = desc -> dt_or_obsolete . scsi_2 . dt_scsi_flags & READ_ELEMENT_STATUS_DT_LUNMASK ; } } }
Copy an element status descriptor to a user-mode
 changer_element_status structure.
Copy an element status descriptor to a user - mode changer_element_status structure .
/* set up logical address in element status */ /* convert source address to logical format */ /*
	 * pvoltag and avoltag are common between SCSI-2 and later versions
	 */ /*
	 * For SCSI-3 and later, element status can carry designator and
	 * other information.
	 */ /* Have both PVOLTAG and AVOLTAG */ /*
			 * Make sure we are always NUL terminated.  The
			 * This won't matter for the binary code set,
			 * since the user will only pay attention to the
			 * length field.
			 */ /* SCSI-SPC and No devid, no designator */