⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsiglue.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	/* Set the TIMED_OUT bit.  Also set the ABORTING bit, but only if	 * a device reset isn't already in progress (to avoid interfering	 * with the reset).  Note that we must retain the host lock while	 * calling usb_stor_stop_transport(); otherwise it might interfere	 * with an auto-reset that begins as soon as we release the lock. */	set_bit(US_FLIDX_TIMED_OUT, &us->flags);	if (!test_bit(US_FLIDX_RESETTING, &us->flags)) {		set_bit(US_FLIDX_ABORTING, &us->flags);		usb_stor_stop_transport(us);	}	scsi_unlock(us_to_host(us));	/* Wait for the aborted command to finish */	wait_for_completion(&us->notify);	return SUCCESS;}/* This invokes the transport reset mechanism to reset the state of the * device */static int device_reset(struct scsi_cmnd *srb){	struct us_data *us = host_to_us(srb->device->host);	int result;	US_DEBUGP("%s called\n", __FUNCTION__);	/* lock the device pointers and do the reset */	down(&(us->dev_semaphore));	result = us->transport_reset(us);	up(&(us->dev_semaphore));	return result < 0 ? FAILED : SUCCESS;}/* Simulate a SCSI bus reset by resetting the device's USB port. */static int bus_reset(struct scsi_cmnd *srb){	struct us_data *us = host_to_us(srb->device->host);	int result;	US_DEBUGP("%s called\n", __FUNCTION__);	down(&(us->dev_semaphore));	result = usb_stor_port_reset(us);	up(&(us->dev_semaphore));	return result < 0 ? FAILED : SUCCESS;}/* Report a driver-initiated device reset to the SCSI layer. * Calling this for a SCSI-initiated reset is unnecessary but harmless. * The caller must own the SCSI host lock. */void usb_stor_report_device_reset(struct us_data *us){	int i;	struct Scsi_Host *host = us_to_host(us);	scsi_report_device_reset(host, 0, 0);	if (us->flags & US_FL_SCM_MULT_TARG) {		for (i = 1; i < host->max_id; ++i)			scsi_report_device_reset(host, 0, i);	}}/* Report a driver-initiated bus reset to the SCSI layer. * Calling this for a SCSI-initiated reset is unnecessary but harmless. * The caller must own the SCSI host lock. */void usb_stor_report_bus_reset(struct us_data *us){	scsi_report_bus_reset(us_to_host(us), 0);}/*********************************************************************** * /proc/scsi/ functions ***********************************************************************//* we use this macro to help us write into the buffer */#undef SPRINTF#define SPRINTF(args...) \	do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)static int proc_info (struct Scsi_Host *host, char *buffer,		char **start, off_t offset, int length, int inout){	struct us_data *us = host_to_us(host);	char *pos = buffer;	const char *string;	/* if someone is sending us data, just throw it away */	if (inout)		return length;	/* print the controller name */	SPRINTF("   Host scsi%d: usb-storage\n", host->host_no);	/* print product, vendor, and serial number strings */	if (us->pusb_dev->manufacturer)		string = us->pusb_dev->manufacturer;	else if (us->unusual_dev->vendorName)		string = us->unusual_dev->vendorName;	else		string = "Unknown";	SPRINTF("       Vendor: %s\n", string);	if (us->pusb_dev->product)		string = us->pusb_dev->product;	else if (us->unusual_dev->productName)		string = us->unusual_dev->productName;	else		string = "Unknown";	SPRINTF("      Product: %s\n", string);	if (us->pusb_dev->serial)		string = us->pusb_dev->serial;	else		string = "None";	SPRINTF("Serial Number: %s\n", string);	/* show the protocol and transport */	SPRINTF("     Protocol: %s\n", us->protocol_name);	SPRINTF("    Transport: %s\n", us->transport_name);	/* show the device flags */	if (pos < buffer + length) {		pos += sprintf(pos, "       Quirks:");#define US_FLAG(name, value) \	if (us->flags & value) pos += sprintf(pos, " " #name);US_DO_ALL_FLAGS#undef US_FLAG		*(pos++) = '\n';	}	/*	 * Calculate start of next buffer, and return value.	 */	*start = buffer + offset;	if ((pos - buffer) < offset)		return (0);	else if ((pos - buffer - offset) < length)		return (pos - buffer - offset);	else		return (length);}/*********************************************************************** * Sysfs interface ***********************************************************************//* Output routine for the sysfs max_sectors file */static ssize_t show_max_sectors(struct device *dev, struct device_attribute *attr, char *buf){	struct scsi_device *sdev = to_scsi_device(dev);	return sprintf(buf, "%u\n", sdev->request_queue->max_sectors);}/* Input routine for the sysfs max_sectors file */static ssize_t store_max_sectors(struct device *dev, struct device_attribute *attr, const char *buf,		size_t count){	struct scsi_device *sdev = to_scsi_device(dev);	unsigned short ms;	if (sscanf(buf, "%hu", &ms) > 0 && ms <= SCSI_DEFAULT_MAX_SECTORS) {		blk_queue_max_sectors(sdev->request_queue, ms);		return strlen(buf);	}	return -EINVAL;	}static DEVICE_ATTR(max_sectors, S_IRUGO | S_IWUSR, show_max_sectors,		store_max_sectors);static struct device_attribute *sysfs_device_attr_list[] = {		&dev_attr_max_sectors,		NULL,		};/* * this defines our host template, with which we'll allocate hosts */struct scsi_host_template usb_stor_host_template = {	/* basic userland interface stuff */	.name =				"usb-storage",	.proc_name =			"usb-storage",	.proc_info =			proc_info,	.info =				host_info,	/* command interface -- queued only */	.queuecommand =			queuecommand,	/* error and abort handlers */	.eh_abort_handler =		command_abort,	.eh_device_reset_handler =	device_reset,	.eh_bus_reset_handler =		bus_reset,	/* queue commands only, only one command per LUN */	.can_queue =			1,	.cmd_per_lun =			1,	/* unknown initiator id */	.this_id =			-1,	.slave_alloc =			slave_alloc,	.slave_configure =		slave_configure,	/* lots of sg segments can be handled */	.sg_tablesize =			SG_ALL,	/* limit the total size of a transfer to 120 KB */	.max_sectors =                  240,	/* merge commands... this seems to help performance, but	 * periodically someone should test to see which setting is more	 * optimal.	 */	.use_clustering =		1,	/* emulated HBA */	.emulated =			1,	/* we do our own delay after a device or bus reset */	.skip_settle_delay =		1,	/* sysfs device attributes */	.sdev_attrs =			sysfs_device_attr_list,	/* module management */	.module =			THIS_MODULE};/* To Report "Illegal Request: Invalid Field in CDB */unsigned char usb_stor_sense_invalidCDB[18] = {	[0]	= 0x70,			    /* current error */	[2]	= ILLEGAL_REQUEST,	    /* Illegal Request = 0x05 */	[7]	= 0x0a,			    /* additional length */	[12]	= 0x24			    /* Invalid Field in CDB */};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -