FreeBSD/lib/libcam/camlib.c
/*
 * Open a given device.  The path argument isn't strictly necessary, but it
 * is copied into the cam_device structure as a convenience to the user.
 */
Open a given device.  The path argument isn't strictly necessary, but it
is copied into the cam_device structure as a convenience to the user.
Open a given device . The path argument isn ' t strictly necessary but it is copied into the cam_device structure as a convenience to the user .
static struct cam_device *
cam_real_open_device(const char *path, int flags, struct cam_device *device,
		     const char *given_path, const char *given_dev_name,
		     int given_unit_number)
{
	char *func_name = "cam_real_open_device";
	union ccb ccb;
	int fd = -1, malloced_device = 0;
	if (device == NULL) {
		if ((device = (struct cam_device *)malloc(
		     sizeof(struct cam_device))) == NULL) {
			snprintf(cam_errbuf, CAM_ERRBUF_SIZE,
				 "%s: device structure malloc"
				 " failed\n%s: %s", func_name, func_name,
				 strerror(errno));
			return(NULL);
		}
		device->fd = -1;
		malloced_device = 1;
	}
	if (given_path != NULL)
		strlcpy(device->device_path, given_path,
			sizeof(device->device_path));
	else
		device->device_path[0] = '\0';
	if (given_dev_name != NULL)
		strlcpy(device->given_dev_name, given_dev_name,
			sizeof(device->given_dev_name));
	else
		device->given_dev_name[0] = '\0';
	device->given_unit_number = given_unit_number;
	if ((fd = open(path, flags)) < 0) {
		snprintf(cam_errbuf, CAM_ERRBUF_SIZE,
			 "%s: couldn't open passthrough device %s\n"
			 "%s: %s", func_name, path, func_name,
			 strerror(errno));
		goto crod_bailout;
	}
	device->fd = fd;
	bzero(&ccb, sizeof(union ccb));
	ccb.ccb_h.func_code = XPT_GDEVLIST;
	if (ioctl(fd, CAMGETPASSTHRU, &ccb) == -1) {
		snprintf(cam_errbuf, CAM_ERRBUF_SIZE,
			 "%s: CAMGETPASSTHRU ioctl failed\n"
			 "%s: %s", func_name, func_name, strerror(errno));
		goto crod_bailout;
	}
	if (ccb.cgdl.status == CAM_GDEVLIST_ERROR) {
		snprintf(cam_errbuf, CAM_ERRBUF_SIZE,
			 "%s: passthrough device does not exist!", func_name);
		goto crod_bailout;
	}
	device->dev_unit_num = ccb.cgdl.unit_number;
	strlcpy(device->device_name, ccb.cgdl.periph_name,
		sizeof(device->device_name));
	device->path_id = ccb.ccb_h.path_id;
	device->target_id = ccb.ccb_h.target_id;
	device->target_lun = ccb.ccb_h.target_lun;
	ccb.ccb_h.func_code = XPT_PATH_INQ;
	if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
		snprintf(cam_errbuf, CAM_ERRBUF_SIZE,
			 "%s: Path Inquiry CCB failed\n"
			 "%s: %s", func_name, func_name, strerror(errno));
		goto crod_bailout;
	}
	strlcpy(device->sim_name, ccb.cpi.dev_name, sizeof(device->sim_name));
	device->sim_unit_number = ccb.cpi.unit_number;
	device->bus_id = ccb.cpi.bus_id;
	ccb.ccb_h.func_code = XPT_GDEV_TYPE;
	if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
		snprintf(cam_errbuf, CAM_ERRBUF_SIZE,
			 "%s: Get Device Type CCB failed\n"
			 "%s: %s", func_name, func_name, strerror(errno));
		goto crod_bailout;
	}
	device->pd_type = SID_TYPE(&ccb.cgd.inq_data);
	bcopy(&ccb.cgd.inq_data, &device->inq_data,
	      sizeof(struct scsi_inquiry_data));
	device->serial_num_len = ccb.cgd.serial_num_len;
	bcopy(&ccb.cgd.serial_num, &device->serial_num, device->serial_num_len);
	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb.cts);
	ccb.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
	ccb.cts.type = CTS_TYPE_CURRENT_SETTINGS;
	if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
		snprintf(cam_errbuf, CAM_ERRBUF_SIZE,
			 "%s: Get Transfer Settings CCB failed\n"
			 "%s: %s", func_name, func_name, strerror(errno));
		goto crod_bailout;
	}
	if (ccb.cts.transport == XPORT_SPI) {
		struct ccb_trans_settings_spi *spi =
		    &ccb.cts.xport_specific.spi;
		device->sync_period = spi->sync_period;
		device->sync_offset = spi->sync_offset;
		device->bus_width = spi->bus_width;
	} else {
		device->sync_period = 0;
		device->sync_offset = 0;
		device->bus_width = 0;
	}
	return(device);
crod_bailout:
	if (fd >= 0)
		close(fd);
	if (malloced_device)
		free(device);
	return(NULL);
}
static struct cam_device * cam_real_open_device ( const char * path , int flags , struct cam_device * device , const char * given_path , const char * given_dev_name , int given_unit_number ) { char * func_name = " " ; union ccb ccb ; int fd = -1 , malloced_device = 0 ; if ( device == NULL ) { if ( ( device = ( struct cam_device * ) malloc ( sizeof ( struct cam_device ) ) ) == NULL ) { snprintf ( cam_errbuf , CAM_ERRBUF_SIZE , " " " \n " , func_name , func_name , strerror ( errno ) ) ; return ( NULL ) ; } device -> fd = -1 ; malloced_device = 1 ; } if ( given_path != NULL ) strlcpy ( device -> device_path , given_path , sizeof ( device -> device_path ) ) ; else device -> device_path [ 0 ] = ' \0 ' ; if ( given_dev_name != NULL ) strlcpy ( device -> given_dev_name , given_dev_name , sizeof ( device -> given_dev_name ) ) ; else device -> given_dev_name [ 0 ] = ' \0 ' ; device -> given_unit_number = given_unit_number ; if ( ( fd = open ( path , flags ) ) < 0 ) { snprintf ( cam_errbuf , CAM_ERRBUF_SIZE , " \n " " " , func_name , path , func_name , strerror ( errno ) ) ; goto crod_bailout ; } device -> fd = fd ; bzero ( & ccb , sizeof ( union ccb ) ) ; ccb . ccb_h . func_code = XPT_GDEVLIST ; if ( ioctl ( fd , CAMGETPASSTHRU , & ccb ) == -1 ) { snprintf ( cam_errbuf , CAM_ERRBUF_SIZE , " \n " " " , func_name , func_name , strerror ( errno ) ) ; goto crod_bailout ; } if ( ccb . cgdl . status == CAM_GDEVLIST_ERROR ) { snprintf ( cam_errbuf , CAM_ERRBUF_SIZE , " " , func_name ) ; goto crod_bailout ; } device -> dev_unit_num = ccb . cgdl . unit_number ; strlcpy ( device -> device_name , ccb . cgdl . periph_name , sizeof ( device -> device_name ) ) ; device -> path_id = ccb . ccb_h . path_id ; device -> target_id = ccb . ccb_h . target_id ; device -> target_lun = ccb . ccb_h . target_lun ; ccb . ccb_h . func_code = XPT_PATH_INQ ; if ( ioctl ( fd , CAMIOCOMMAND , & ccb ) == -1 ) { snprintf ( cam_errbuf , CAM_ERRBUF_SIZE , " \n " " " , func_name , func_name , strerror ( errno ) ) ; goto crod_bailout ; } strlcpy ( device -> sim_name , ccb . cpi . dev_name , sizeof ( device -> sim_name ) ) ; device -> sim_unit_number = ccb . cpi . unit_number ; device -> bus_id = ccb . cpi . bus_id ; ccb . ccb_h . func_code = XPT_GDEV_TYPE ; if ( ioctl ( fd , CAMIOCOMMAND , & ccb ) == -1 ) { snprintf ( cam_errbuf , CAM_ERRBUF_SIZE , " \n " " " , func_name , func_name , strerror ( errno ) ) ; goto crod_bailout ; } device -> pd_type = SID_TYPE ( & ccb . cgd . inq_data ) ; bcopy ( & ccb . cgd . inq_data , & device -> inq_data , sizeof ( struct scsi_inquiry_data ) ) ; device -> serial_num_len = ccb . cgd . serial_num_len ; bcopy ( & ccb . cgd . serial_num , & device -> serial_num , device -> serial_num_len ) ; CCB_CLEAR_ALL_EXCEPT_HDR ( & ccb . cts ) ; ccb . ccb_h . func_code = XPT_GET_TRAN_SETTINGS ; ccb . cts . type = CTS_TYPE_CURRENT_SETTINGS ; if ( ioctl ( fd , CAMIOCOMMAND , & ccb ) == -1 ) { snprintf ( cam_errbuf , CAM_ERRBUF_SIZE , " \n " " " , func_name , func_name , strerror ( errno ) ) ; goto crod_bailout ; } if ( ccb . cts . transport == XPORT_SPI ) { struct ccb_trans_settings_spi * spi = & ccb . cts . xport_specific . spi ; device -> sync_period = spi -> sync_period ; device -> sync_offset = spi -> sync_offset ; device -> bus_width = spi -> bus_width ; } else { device -> sync_period = 0 ; device -> sync_offset = 0 ; device -> bus_width = 0 ; } return ( device ) ; crod_bailout : if ( fd >= 0 ) close ( fd ) ; if ( malloced_device ) free ( device ) ; return ( NULL ) ; }
Open a given device.
Open a given device .
/*
	 * See if the user wants us to malloc a device for him.
	 */ /*
	 * If the user passed in a path, save it for him.
	 */ /*
	 * If the user passed in a device name and unit number pair, save
	 * those as well.
	 */ /*
	 * Unlike the transport layer version of the GETPASSTHRU ioctl,
	 * we don't have to set any fields.
	 */ /*
	 * We're only doing this to get some information on the device in
	 * question.  Otherwise, we'd have to pass in yet another
	 * parameter: the passthrough driver unit number.
	 */ /*
		 * At this point we know the passthrough device must exist
		 * because we just opened it above.  The only way this
		 * ioctl can fail is if the ccb size is wrong.
		 */ /*
	 * If the ioctl returned the right status, but we got an error back
	 * in the ccb, that means that the kernel found the device the user
	 * passed in, but was unable to find the passthrough device for
	 * the device the user gave us.
	 */ /*
	 * It doesn't really matter what is in the payload for a getdev
	 * CCB, the kernel doesn't look at it.
	 */ /*
	 * Zero the payload, the kernel does look at the flags.
	 */ /*
	 * Get transfer settings for this device.
	 */