📄 scsiglue.c
字号:
} /* 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 + -