FreeBSD/lib/libcam/camlib.c
/*
 * Open the passthrough device for a given bus, target and lun, if the
 * passthrough device exists.
 */
Open the passthrough device for a given bus, target and lun, if the
passthrough device exists.
Open the passthrough device for a given bus target and lun if the passthrough device exists .
struct cam_device *
cam_open_btl(path_id_t path_id, target_id_t target_id, lun_id_t target_lun,
	     int flags, struct cam_device *device)
{
	union ccb ccb;
	struct periph_match_pattern *match_pat;
	char *func_name = "cam_open_btl";
	int fd, bufsize;
	if ((fd = open(XPT_DEVICE, O_RDWR)) < 0) {
		snprintf(cam_errbuf, CAM_ERRBUF_SIZE,
			 "%s: couldn't open %s\n%s: %s", func_name, XPT_DEVICE,
			 func_name, strerror(errno));
		return(NULL);
	}
	bzero(&ccb, sizeof(union ccb));
	ccb.ccb_h.func_code = XPT_DEV_MATCH;
	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
	bufsize = sizeof(struct dev_match_result);
	ccb.cdm.match_buf_len = bufsize;
	ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
	if (ccb.cdm.matches == NULL) {
		snprintf(cam_errbuf, CAM_ERRBUF_SIZE,
			 "%s: couldn't malloc match buffer", func_name);
		close(fd);
		return(NULL);
	}
	ccb.cdm.num_matches = 0;
	ccb.cdm.num_patterns = 1;
	ccb.cdm.pattern_buf_len = sizeof(struct dev_match_pattern);
	ccb.cdm.patterns = (struct dev_match_pattern *)malloc(
		sizeof(struct dev_match_pattern));
	if (ccb.cdm.patterns == NULL) {
		snprintf(cam_errbuf, CAM_ERRBUF_SIZE,
			 "%s: couldn't malloc pattern buffer", func_name);
		free(ccb.cdm.matches);
		close(fd);
		return(NULL);
	}
	ccb.cdm.patterns[0].type = DEV_MATCH_PERIPH;
	match_pat = &ccb.cdm.patterns[0].pattern.periph_pattern;
	sprintf(match_pat->periph_name, "pass");
	match_pat->path_id = path_id;
	match_pat->target_id = target_id;
	match_pat->target_lun = target_lun;
	match_pat->flags = PERIPH_MATCH_PATH | PERIPH_MATCH_TARGET |
			   PERIPH_MATCH_LUN | PERIPH_MATCH_NAME;
	if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
		snprintf(cam_errbuf, CAM_ERRBUF_SIZE,
			 "%s: CAMIOCOMMAND ioctl failed\n"
			 "%s: %s", func_name, func_name, strerror(errno));
		goto btl_bailout;
	}
	if ((ccb.ccb_h.status != CAM_REQ_CMP)
	 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
	   && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
		snprintf(cam_errbuf, CAM_ERRBUF_SIZE,
			 "%s: CAM error %#x, CDM error %d "
			 "returned from XPT_DEV_MATCH ccb", func_name,
			 ccb.ccb_h.status, ccb.cdm.status);
		goto btl_bailout;
	}
	if (ccb.cdm.status == CAM_DEV_MATCH_MORE) {
		snprintf(cam_errbuf, CAM_ERRBUF_SIZE,
			 "%s: CDM reported more than one"
			 " passthrough device at %d:%d:%jx!!\n",
			 func_name, path_id, target_id, (uintmax_t)target_lun);
		goto btl_bailout;
	}
	if (ccb.cdm.num_matches == 0) {
		snprintf(cam_errbuf, CAM_ERRBUF_SIZE,
			 "%s: no passthrough device found at"
			 " %d:%d:%jx", func_name, path_id, target_id,
			 (uintmax_t)target_lun);
		goto btl_bailout;
	}
	switch(ccb.cdm.matches[0].type) {
	case DEV_MATCH_PERIPH: {
		int pass_unit;
		char dev_path[256];
		struct periph_match_result *periph_result;
		periph_result = &ccb.cdm.matches[0].result.periph_result;
		pass_unit = periph_result->unit_number;
		free(ccb.cdm.matches);
		free(ccb.cdm.patterns);
		close(fd);
		sprintf(dev_path, "/dev/pass%d", pass_unit);
		return(cam_real_open_device(dev_path, flags, device, NULL,
					    NULL, 0));
		break; 
	}
	default:
		snprintf(cam_errbuf, CAM_ERRBUF_SIZE,
			 "%s: asked for a peripheral match, but"
			 " got a bus or device match", func_name);
		goto btl_bailout;
		break; 
	}
btl_bailout:
	free(ccb.cdm.matches);
	free(ccb.cdm.patterns);
	close(fd);
	return(NULL);
}
struct cam_device * cam_open_btl ( path_id_t path_id , target_id_t target_id , lun_id_t target_lun , int flags , struct cam_device * device ) { union ccb ccb ; struct periph_match_pattern * match_pat ; char * func_name = " " ; int fd , bufsize ; if ( ( fd = open ( XPT_DEVICE , O_RDWR ) ) < 0 ) { snprintf ( cam_errbuf , CAM_ERRBUF_SIZE , " \n " , func_name , XPT_DEVICE , func_name , strerror ( errno ) ) ; return ( NULL ) ; } bzero ( & ccb , sizeof ( union ccb ) ) ; ccb . ccb_h . func_code = XPT_DEV_MATCH ; ccb . ccb_h . path_id = CAM_XPT_PATH_ID ; ccb . ccb_h . target_id = CAM_TARGET_WILDCARD ; ccb . ccb_h . target_lun = CAM_LUN_WILDCARD ; bufsize = sizeof ( struct dev_match_result ) ; ccb . cdm . match_buf_len = bufsize ; ccb . cdm . matches = ( struct dev_match_result * ) malloc ( bufsize ) ; if ( ccb . cdm . matches == NULL ) { snprintf ( cam_errbuf , CAM_ERRBUF_SIZE , " " , func_name ) ; close ( fd ) ; return ( NULL ) ; } ccb . cdm . num_matches = 0 ; ccb . cdm . num_patterns = 1 ; ccb . cdm . pattern_buf_len = sizeof ( struct dev_match_pattern ) ; ccb . cdm . patterns = ( struct dev_match_pattern * ) malloc ( sizeof ( struct dev_match_pattern ) ) ; if ( ccb . cdm . patterns == NULL ) { snprintf ( cam_errbuf , CAM_ERRBUF_SIZE , " " , func_name ) ; free ( ccb . cdm . matches ) ; close ( fd ) ; return ( NULL ) ; } ccb . cdm . patterns [ 0 ] . type = DEV_MATCH_PERIPH ; match_pat = & ccb . cdm . patterns [ 0 ] . pattern . periph_pattern ; sprintf ( match_pat -> periph_name , " " ) ; match_pat -> path_id = path_id ; match_pat -> target_id = target_id ; match_pat -> target_lun = target_lun ; match_pat -> flags = PERIPH_MATCH_PATH | PERIPH_MATCH_TARGET | PERIPH_MATCH_LUN | PERIPH_MATCH_NAME ; if ( ioctl ( fd , CAMIOCOMMAND , & ccb ) == -1 ) { snprintf ( cam_errbuf , CAM_ERRBUF_SIZE , " \n " " " , func_name , func_name , strerror ( errno ) ) ; goto btl_bailout ; } if ( ( ccb . ccb_h . status != CAM_REQ_CMP ) || ( ( ccb . cdm . status != CAM_DEV_MATCH_LAST ) && ( ccb . cdm . status != CAM_DEV_MATCH_MORE ) ) ) { snprintf ( cam_errbuf , CAM_ERRBUF_SIZE , " " " " , func_name , ccb . ccb_h . status , ccb . cdm . status ) ; goto btl_bailout ; } if ( ccb . cdm . status == CAM_DEV_MATCH_MORE ) { snprintf ( cam_errbuf , CAM_ERRBUF_SIZE , " " " \n " , func_name , path_id , target_id , ( uintmax_t ) target_lun ) ; goto btl_bailout ; } if ( ccb . cdm . num_matches == 0 ) { snprintf ( cam_errbuf , CAM_ERRBUF_SIZE , " " " " , func_name , path_id , target_id , ( uintmax_t ) target_lun ) ; goto btl_bailout ; } switch ( ccb . cdm . matches [ 0 ] . type ) { case DEV_MATCH_PERIPH : { int pass_unit ; char dev_path [ 256 ] ; struct periph_match_result * periph_result ; periph_result = & ccb . cdm . matches [ 0 ] . result . periph_result ; pass_unit = periph_result -> unit_number ; free ( ccb . cdm . matches ) ; free ( ccb . cdm . patterns ) ; close ( fd ) ; sprintf ( dev_path , " " , pass_unit ) ; return ( cam_real_open_device ( dev_path , flags , device , NULL , NULL , 0 ) ) ; break ; } default : snprintf ( cam_errbuf , CAM_ERRBUF_SIZE , " " " " , func_name ) ; goto btl_bailout ; break ; } btl_bailout : free ( ccb . cdm . matches ) ; free ( ccb . cdm . patterns ) ; close ( fd ) ; return ( NULL ) ; }
Open the passthrough device for a given bus, target and lun, if the
 passthrough device exists.
Open the passthrough device for a given bus target and lun if the passthrough device exists .
/* Setup the result buffer */ /* Setup the pattern buffer */ /*
	 * We're looking for the passthrough device associated with this
	 * particular bus/target/lun.
	 */ /* Now set the flags to indicate what we're looking for. */ /*
	 * Check for an outright error.
	 */ /* NOTREACHED */ /* NOTREACHED */