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

📄 csk_udisk_mgr.c

📁 linux 2.6.13 USB2.0开发补丁,lyj_uptech@126.com
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* fill and submit the URB */	usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe, 			 (unsigned char*) us->cr, data, size, 			 usb_stor_blocking_completion, NULL);	status = usb_stor_msg_common(us, timeout);	/* return the actual length of the data transferred if no error */	if (status == 0)		status = us->current_urb->actual_length;	return status;}/* This is the common part of the URB message submission code * * All URBs from the usb-storage driver involved in handling a queued scsi * command _must_ pass through this function (or something like it) for the * abort mechanisms to work properly. */static int usb_stor_msg_common(struct us_data *us, int timeout){	struct completion urb_done;	long timeleft;	int status;	/* don't submit URBs during abort/disconnect processing */	if (us->flags & ABORTING_OR_DISCONNECTING)		return -EIO;	/* set up data structures for the wakeup system */	init_completion(&urb_done);	/* fill the common fields in the URB */	us->current_urb->context = &urb_done;	us->current_urb->actual_length = 0;	us->current_urb->error_count = 0;	us->current_urb->status = 0;	us->current_urb->transfer_flags = URB_NO_SETUP_DMA_MAP;	if (us->current_urb->transfer_buffer == us->iobuf)		us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;	us->current_urb->transfer_dma = us->iobuf_dma;	us->current_urb->setup_dma = us->cr_dma;	/* submit the URB */	status = usb_submit_urb(us->current_urb, GFP_NOIO);	if (status) {		/* something went wrong */		return status;	}	/* since the URB has been submitted successfully, it's now okay	 * to cancel it */	set_bit(US_FLIDX_URB_ACTIVE, &us->flags);	/* did an abort/disconnect occur during the submission? */	if (us->flags & ABORTING_OR_DISCONNECTING) {		/* cancel the URB, if it hasn't been cancelled already */		if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) {					usb_unlink_urb(us->current_urb);		}	} 	/* wait for the completion of the URB */	timeleft = wait_for_completion_interruptible_timeout(			&urb_done, timeout ? : MAX_SCHEDULE_TIMEOUT); 	clear_bit(US_FLIDX_URB_ACTIVE, &us->flags);	if (timeleft <= 0) {		usb_kill_urb(us->current_urb);	}	/* return the URB status */	return us->current_urb->status;}/* * Interpret the results of a URB transfer * * This function prints appropriate debugging messages, clears halts on * non-control endpoints, and translates the status to the corresponding * USB_STOR_XFER_xxx return code. */static int interpret_urb_result(struct us_data *us, unsigned int pipe,		unsigned int length, int result, unsigned int partial){		switch (result) {	/* no error code; did we send all the data? */	case 0:		if (partial != length) {					return USB_STOR_XFER_SHORT;		}				return USB_STOR_XFER_GOOD;	/* stalled */	case -EPIPE:		/* for control endpoints, (used by CB[I]) a stall indicates		 * a failed command */		if (usb_pipecontrol(pipe)) {					return USB_STOR_XFER_STALLED;		}		/* for other sorts of endpoint, clear the stall */				if (usb_stor_clear_halt(us, pipe) < 0)			return USB_STOR_XFER_ERROR;		return USB_STOR_XFER_STALLED;	/* babble - the device tried to send more than we wanted to read */	case -EOVERFLOW:				return USB_STOR_XFER_LONG;	/* the transfer was cancelled by abort, disconnect, or timeout */	case -ECONNRESET:				return USB_STOR_XFER_ERROR;	/* short scatter-gather read transfer */	case -EREMOTEIO:			return USB_STOR_XFER_SHORT;	/* abort or disconnect in progress */	case -EIO:			return USB_STOR_XFER_ERROR;	/* the catch-all error case */	default:			return USB_STOR_XFER_ERROR;	}}static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,		struct scatterlist *sg, int num_sg, unsigned int length,		unsigned int *act_len){	int result;	/* don't submit s-g requests during abort/disconnect processing */	if (us->flags & ABORTING_OR_DISCONNECTING)		return USB_STOR_XFER_ERROR;	/* initialize the scatter-gather request block */		result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0,			sg, num_sg, length, GFP_NOIO);	if (result) {			return USB_STOR_XFER_ERROR;	}	/* since the block has been initialized successfully, it's now	 * okay to cancel it */	set_bit(US_FLIDX_SG_ACTIVE, &us->flags);	/* did an abort/disconnect occur during the submission? */	if (us->flags & ABORTING_OR_DISCONNECTING) {		/* cancel the request, if it hasn't been cancelled already */		if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) {						usb_sg_cancel(&us->current_sg);		}	}	/* wait for the completion of the transfer */	usb_sg_wait(&us->current_sg);	clear_bit(US_FLIDX_SG_ACTIVE, &us->flags);	result = us->current_sg.status;	if (act_len)		*act_len = us->current_sg.bytes;	return interpret_urb_result(us, pipe, length, result,			us->current_sg.bytes);}/* Determine what the maximum LUN supported is */static int usb_stor_Bulk_max_lun(struct us_data *us){	int result;	/* issue the command */	us->iobuf[0] = 0;	result = usb_stor_control_msg(us, us->recv_ctrl_pipe,				 US_BULK_GET_MAX_LUN, 				 USB_DIR_IN | USB_TYPE_CLASS | 				 USB_RECIP_INTERFACE,				 0, us->ifnum, us->iobuf, 1, HZ);		/* if we have a successful request, return the result */	if (result > 0)		return us->iobuf[0];	if (result == -EPIPE) {		usb_stor_clear_halt(us, us->recv_bulk_pipe);		usb_stor_clear_halt(us, us->send_bulk_pipe);	}	return 0;}static void usb_stor_blocking_completion(struct urb *urb){	struct completion *urb_done_ptr = (struct completion *)urb->context;	complete(urb_done_ptr);}/* 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);	printk("show_max_sectors:%u\n",sdev->request_queue->max_sectors);	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 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);	string = us->pusb_dev->manufacturer;	SPRINTF("       Vendor: %s\n", string);	string = us->pusb_dev->product;	SPRINTF("      Product: %s\n", string);	string = "None";	SPRINTF("Serial Number: %s\n", string);	/* show the protocol and transport */	/* show the device flags */	if (pos < buffer + length) {		pos += sprintf(pos, "       Quirks:");		*(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);}static const char* host_info(struct Scsi_Host *host){	return "SCSI emulation for SAMSUNG mobile";}static int queuecommand(struct scsi_cmnd *srb,			void (*done)(struct scsi_cmnd *)){	struct us_data *us = host_to_us(srb->device->host);	if (us->srb != NULL) {		printk(KERN_ERR "Error in %s: us->srb = %p\n",			__FUNCTION__, us->srb);		return SCSI_MLQUEUE_HOST_BUSY;	}		if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {			srb->result = DID_NO_CONNECT << 16;		done(srb);		return 0;	}	/* enqueue the command and wake up the control thread */	srb->scsi_done = done;	us->srb = srb;	up(&(us->sema));	return 0;}static int command_abort(struct scsi_cmnd *srb){	struct us_data *us = host_to_us(srb->device->host);	scsi_lock(us_to_host(us));	/* Is this command still active? */	if (us->srb != srb) {		scsi_unlock(us_to_host(us));		return FAILED;	}	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;}static int device_reset(struct scsi_cmnd *srb){	struct us_data *us = host_to_us(srb->device->host);	int result;	/* lock the device pointers and do the reset */	mutex_lock(&(us->dev_mutex));	result = usb_stor_Bulk_reset(us);	mutex_unlock(&us->dev_mutex);	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;	result = usb_stor_port_reset(us);	return result < 0 ? FAILED : SUCCESS;}static int slave_alloc (struct scsi_device *sdev){	struct us_data *us = host_to_us(sdev->host);	sdev->inquiry_len = 36;	return 0;}static int slave_configure(struct scsi_device *sdev){	struct us_data *us = host_to_us(sdev->host);	blk_queue_dma_alignment(sdev->request_queue, (512 - 1));		if (sdev->scsi_level < SCSI_2)		sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2;		if ((us->flags & US_FL_MAX_SECTORS_64) &&			sdev->request_queue->max_sectors > 64)		blk_queue_max_sectors(sdev->request_queue, 64);		if (sdev->type == TYPE_DISK) {					sdev->use_10_for_ms = 1;				sdev->use_192_bytes_for_3f = 1;		if (us->flags & US_FL_NO_WP_DETECT)			sdev->skip_ms_page_3f = 1;				sdev->skip_ms_page_8 = 1;				if (us->flags & US_FL_FIX_CAPACITY)			sdev->fix_capacity = 1;				sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2;				sdev->retry_hwerror = 1;	} else {				sdev->use_10_for_ms = 1;	}		if (us->flags & US_FL_NOT_LOCKABLE)		sdev->lockable = 0;		return 0;}

⌨️ 快捷键说明

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