FreeBSD/sys/cam/ctl/ctl.c
/*
 * SCSI VPD page 0x83, the Device Identification page.
 */
SCSI VPD page 0x83, the Device Identification page.
SCSI VPD page 0x83 the Device Identification page .
static int
ctl_inquiry_evpd_devid(struct ctl_scsiio *ctsio, int alloc_len)
{
	struct scsi_vpd_device_id *devid_ptr;
	struct scsi_vpd_id_descriptor *desc;
	struct ctl_softc *softc;
	struct ctl_lun *lun;
	struct ctl_port *port;
	int data_len, g;
	uint8_t proto;
	softc = control_softc;
	port = ctl_io_port(&ctsio->io_hdr);
	lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
	data_len = sizeof(struct scsi_vpd_device_id) +
	    sizeof(struct scsi_vpd_id_descriptor) +
		sizeof(struct scsi_vpd_id_rel_trgt_port_id) +
	    sizeof(struct scsi_vpd_id_descriptor) +
		sizeof(struct scsi_vpd_id_trgt_port_grp_id);
	if (lun && lun->lun_devid)
		data_len += lun->lun_devid->len;
	if (port && port->port_devid)
		data_len += port->port_devid->len;
	if (port && port->target_devid)
		data_len += port->target_devid->len;
	ctsio->kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
	devid_ptr = (struct scsi_vpd_device_id *)ctsio->kern_data_ptr;
	ctsio->kern_sg_entries = 0;
	if (data_len < alloc_len) {
		ctsio->residual = alloc_len - data_len;
		ctsio->kern_data_len = data_len;
		ctsio->kern_total_len = data_len;
	} else {
		ctsio->residual = 0;
		ctsio->kern_data_len = alloc_len;
		ctsio->kern_total_len = alloc_len;
	}
	ctsio->kern_data_resid = 0;
	ctsio->kern_rel_offset = 0;
	ctsio->kern_sg_entries = 0;
	if (lun != NULL)
		devid_ptr->device = (SID_QUAL_LU_CONNECTED << 5) |
				     lun->be_lun->lun_type;
	else
		devid_ptr->device = (SID_QUAL_LU_OFFLINE << 5) | T_DIRECT;
	devid_ptr->page_code = SVPD_DEVICE_ID;
	scsi_ulto2b(data_len - 4, devid_ptr->length);
	if (port && port->port_type == CTL_PORT_FC)
		proto = SCSI_PROTO_FC << 4;
	else if (port && port->port_type == CTL_PORT_ISCSI)
		proto = SCSI_PROTO_ISCSI << 4;
	else
		proto = SCSI_PROTO_SPI << 4;
	desc = (struct scsi_vpd_id_descriptor *)devid_ptr->desc_list;
	if (lun && lun->lun_devid) {
		memcpy(desc, lun->lun_devid->data, lun->lun_devid->len);
		desc = (struct scsi_vpd_id_descriptor *)((uint8_t *)desc +
		    lun->lun_devid->len);
	}
	if (port && port->port_devid) {
		memcpy(desc, port->port_devid->data, port->port_devid->len);
		desc = (struct scsi_vpd_id_descriptor *)((uint8_t *)desc +
		    port->port_devid->len);
	}
	desc->proto_codeset = proto | SVPD_ID_CODESET_BINARY;
	desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT |
	    SVPD_ID_TYPE_RELTARG;
	desc->length = 4;
	scsi_ulto2b(ctsio->io_hdr.nexus.targ_port, &desc->identifier[2]);
	desc = (struct scsi_vpd_id_descriptor *)(&desc->identifier[0] +
	    sizeof(struct scsi_vpd_id_rel_trgt_port_id));
	desc->proto_codeset = proto | SVPD_ID_CODESET_BINARY;
	desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT |
	    SVPD_ID_TYPE_TPORTGRP;
	desc->length = 4;
	if (softc->is_single ||
	    (port && port->status & CTL_PORT_STATUS_HA_SHARED))
		g = 1;
	else
		g = 2 + ctsio->io_hdr.nexus.targ_port / softc->port_cnt;
	scsi_ulto2b(g, &desc->identifier[2]);
	desc = (struct scsi_vpd_id_descriptor *)(&desc->identifier[0] +
	    sizeof(struct scsi_vpd_id_trgt_port_grp_id));
	if (port && port->target_devid) {
		memcpy(desc, port->target_devid->data, port->target_devid->len);
	}
	ctl_set_success(ctsio);
	ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
	ctsio->be_move_done = ctl_config_move_done;
	ctl_datamove((union ctl_io *)ctsio);
	return (CTL_RETVAL_COMPLETE);
}
static int ctl_inquiry_evpd_devid ( struct ctl_scsiio * ctsio , int alloc_len ) { struct scsi_vpd_device_id * devid_ptr ; struct scsi_vpd_id_descriptor * desc ; struct ctl_softc * softc ; struct ctl_lun * lun ; struct ctl_port * port ; int data_len , g ; uint8_t proto ; softc = control_softc ; port = ctl_io_port ( & ctsio -> io_hdr ) ; lun = ( struct ctl_lun * ) ctsio -> io_hdr . ctl_private [ CTL_PRIV_LUN ] . ptr ; data_len = sizeof ( struct scsi_vpd_device_id ) + sizeof ( struct scsi_vpd_id_descriptor ) + sizeof ( struct scsi_vpd_id_rel_trgt_port_id ) + sizeof ( struct scsi_vpd_id_descriptor ) + sizeof ( struct scsi_vpd_id_trgt_port_grp_id ) ; if ( lun && lun -> lun_devid ) data_len += lun -> lun_devid -> len ; if ( port && port -> port_devid ) data_len += port -> port_devid -> len ; if ( port && port -> target_devid ) data_len += port -> target_devid -> len ; ctsio -> kern_data_ptr = malloc ( data_len , M_CTL , M_WAITOK | M_ZERO ) ; devid_ptr = ( struct scsi_vpd_device_id * ) ctsio -> kern_data_ptr ; ctsio -> kern_sg_entries = 0 ; if ( data_len < alloc_len ) { ctsio -> residual = alloc_len - data_len ; ctsio -> kern_data_len = data_len ; ctsio -> kern_total_len = data_len ; } else { ctsio -> residual = 0 ; ctsio -> kern_data_len = alloc_len ; ctsio -> kern_total_len = alloc_len ; } ctsio -> kern_data_resid = 0 ; ctsio -> kern_rel_offset = 0 ; ctsio -> kern_sg_entries = 0 ; if ( lun != NULL ) devid_ptr -> device = ( SID_QUAL_LU_CONNECTED << 5 ) | lun -> be_lun -> lun_type ; else devid_ptr -> device = ( SID_QUAL_LU_OFFLINE << 5 ) | T_DIRECT ; devid_ptr -> page_code = SVPD_DEVICE_ID ; scsi_ulto2b ( data_len - 4 , devid_ptr -> length ) ; if ( port && port -> port_type == CTL_PORT_FC ) proto = SCSI_PROTO_FC << 4 ; else if ( port && port -> port_type == CTL_PORT_ISCSI ) proto = SCSI_PROTO_ISCSI << 4 ; else proto = SCSI_PROTO_SPI << 4 ; desc = ( struct scsi_vpd_id_descriptor * ) devid_ptr -> desc_list ; if ( lun && lun -> lun_devid ) { memcpy ( desc , lun -> lun_devid -> data , lun -> lun_devid -> len ) ; desc = ( struct scsi_vpd_id_descriptor * ) ( ( uint8_t * ) desc + lun -> lun_devid -> len ) ; } if ( port && port -> port_devid ) { memcpy ( desc , port -> port_devid -> data , port -> port_devid -> len ) ; desc = ( struct scsi_vpd_id_descriptor * ) ( ( uint8_t * ) desc + port -> port_devid -> len ) ; } desc -> proto_codeset = proto | SVPD_ID_CODESET_BINARY ; desc -> id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT | SVPD_ID_TYPE_RELTARG ; desc -> length = 4 ; scsi_ulto2b ( ctsio -> io_hdr . nexus . targ_port , & desc -> identifier [ 2 ] ) ; desc = ( struct scsi_vpd_id_descriptor * ) ( & desc -> identifier [ 0 ] + sizeof ( struct scsi_vpd_id_rel_trgt_port_id ) ) ; desc -> proto_codeset = proto | SVPD_ID_CODESET_BINARY ; desc -> id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT | SVPD_ID_TYPE_TPORTGRP ; desc -> length = 4 ; if ( softc -> is_single || ( port && port -> status & CTL_PORT_STATUS_HA_SHARED ) ) g = 1 ; else g = 2 + ctsio -> io_hdr . nexus . targ_port / softc -> port_cnt ; scsi_ulto2b ( g , & desc -> identifier [ 2 ] ) ; desc = ( struct scsi_vpd_id_descriptor * ) ( & desc -> identifier [ 0 ] + sizeof ( struct scsi_vpd_id_trgt_port_grp_id ) ) ; if ( port && port -> target_devid ) { memcpy ( desc , port -> target_devid -> data , port -> target_devid -> len ) ; } ctl_set_success ( ctsio ) ; ctsio -> io_hdr . flags |= CTL_FLAG_ALLOCATED ; ctsio -> be_move_done = ctl_config_move_done ; ctl_datamove ( ( union ctl_io * ) ctsio ) ; return ( CTL_RETVAL_COMPLETE ) ; }
SCSI VPD page 0x83, the Device Identification page.
SCSI VPD page 0x83 the Device Identification page .
/*
	 * The control device is always connected.  The disk device, on the
	 * other hand, may not be online all the time.
	 */ /*
	 * We're using a LUN association here.  i.e., this device ID is a
	 * per-LUN identifier.
	 */ /*
	 * This is for the WWPN which is a port association.
	 */ /*
	 * This is for the Relative Target Port(type 4h) identifier
	 */ /*
	 * This is for the Target Port Group(type 5h) identifier
	 */ /*
	 * This is for the Target identifier
	 */