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

📄 csk_udisk_mgr.c

📁 linux 2.6.13 USB2.0开发补丁,lyj_uptech@126.com
💻 C
📖 第 1 页 / 共 4 页
字号:
				ep_in = ep;			else				ep_out = ep;		}		/* Is it an interrupt endpoint? */		else if (usb_endpoint_xfer_int(ep)) {			ep_int = ep;		}	}	if (!ep_in || !ep_out) {		goto BadDevice;		}	/* Calculate and store the pipe values */	us->send_ctrl_pipe = usb_sndctrlpipe(us->pusb_dev, 0);	us->recv_ctrl_pipe = usb_rcvctrlpipe(us->pusb_dev, 0);	us->send_bulk_pipe = usb_sndbulkpipe(us->pusb_dev,		ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);	us->recv_bulk_pipe = usb_rcvbulkpipe(us->pusb_dev, 		ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);	if (ep_int) {		us->recv_intr_pipe = usb_rcvintpipe(us->pusb_dev,			ep_int->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);		us->ep_bInterval = ep_int->bInterval;	}	//////	us->current_urb = usb_alloc_urb(0, GFP_KERNEL);	if (!us->current_urb) {		goto BadDevice;		}	th = kthread_create(usb_worker, us, "csk-usb-storage");	if (IS_ERR(th)) {		printk(KERN_WARNING "Unable to start control thread\n");		goto BadDevice;		}	/* Take a reference to the host for the control thread and	* count it among all the threads we have launched.  Then	* start it up. */	scsi_host_get(us_to_host(us));	atomic_inc(&g_total_workers);	wake_up_process(th);		Ans = scsi_add_host(host, &intf->dev);	if (Ans) {		printk(KERN_WARNING "Unable to add the scsi host\n");		goto BadDevice;	}	/////	printk(KERN_DEBUG		"SUMANG MOBILE device found at %d\n", us->pusb_dev->devnum);	/* If the device is still connected, perform the scanning */	if (!test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {		/* For bulk-only devices, determine the max LUN value */		if (!(us->flags & US_FL_SINGLE_LUN)) {			mutex_lock(&us->dev_mutex);			/////			/* issue the command */			us->iobuf[0] = 0;			Ans = 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 (Ans > 0)			{				us->max_lun = us->iobuf[0];			}						if (Ans == -EPIPE) {				usb_stor_clear_halt(us, us->recv_bulk_pipe);				usb_stor_clear_halt(us, us->send_bulk_pipe);			}			////			mutex_unlock(&us->dev_mutex);		}		scsi_scan_host(us_to_host(us));		printk(KERN_DEBUG "device scan complete\n");		/* Should we unbind if no devices were detected? */	}	scsi_host_put(us_to_host(us));	scsi_host_get(us_to_host(us));	/////	return 0;	/* We come here if there are any problems */BadDevice:	FreeUpAll(us);	return -EPIPE;}//go home and have a rest..static void storage_disconnect(struct usb_interface *i){	struct us_data *us = usb_get_intfdata(i);	quiesce_and_remove_host(us);	FreeUpAll(us);}static struct usb_driver usb_storage_driver = {	.name =		"csk-usb-storage",	.probe =	storage_probe,	.disconnect =	storage_disconnect,	.pre_reset =	storage_pre_reset,	.post_reset =	storage_post_reset,	.id_table =	storage_usb_ids,};static int __init mod_init(void){	int ans;	if ((ans = usb_register(&usb_storage_driver)) == 0)	{		printk(KERN_INFO "CSK's USB Mass Storage driver,Loaded\n");	}	return ans;}static void __exit mod_exit(void){	usb_deregister(&usb_storage_driver) ;}module_init(mod_init);module_exit(mod_exit);static void FreeUpAll(struct us_data *us){	set_bit(US_FLIDX_DISCONNECTING, &us->flags);	//let our worker suspend	up(&us->sema);	usb_free_urb(us->current_urb);	kfree(us->sensebuf);	if (us->cr)		usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr,		us->cr_dma);	if (us->iobuf)		usb_buffer_free(us->pusb_dev, US_IOBUF_SIZE, us->iobuf,		us->iobuf_dma);	usb_set_intfdata(us->pusb_intf, NULL);	scsi_host_put(us_to_host(us));}static void quiesce_and_remove_host(struct us_data *us){	struct Scsi_Host *host = us_to_host(us);	scsi_lock(host);	set_bit(US_FLIDX_DISCONNECTING, &us->flags);	scsi_unlock(host);	usb_stor_stop_transport(us);	wake_up(&us->delay_wait);	mutex_lock(&us->dev_mutex);	if (us->srb) {		us->srb->result = DID_NO_CONNECT << 16;		scsi_lock(host);		us->srb->scsi_done(us->srb);		us->srb = NULL;		scsi_unlock(host);	}	mutex_unlock(&us->dev_mutex);	/* Now we own no commands so it's safe to remove the SCSI host */	scsi_remove_host(host);}/* Invoke the transport and basic error-handling/recovery methods * * This is used by the protocol layers to actually send the message to * the device and receive the response. */static void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us){	int need_auto_sense;	int result;	/* send the command to the transport layer */	srb->resid = 0;	result = usb_stor_Bulk_transport(srb, us);	/* if the command gets aborted by the higher layers, we need to	 * short-circuit all other processing	 */	if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {				srb->result = DID_ABORT << 16;		goto Handle_Errors;	}	/* if there is a transport error, reset and don't auto-sense */	if (result == USB_STOR_TRANSPORT_ERROR) {				srb->result = DID_ERROR << 16;		goto Handle_Errors;	}	/* if the transport provided its own sense data, don't auto-sense */	if (result == USB_STOR_TRANSPORT_NO_SENSE) {		srb->result = SAM_STAT_CHECK_CONDITION;		return;	}	srb->result = SAM_STAT_GOOD;	/* Determine if we need to auto-sense	 *	 * I normally don't use a flag like this, but it's almost impossible	 * to understand what's going on here if I don't.	 */	need_auto_sense = 0;	/*	 * If we have a failure, we're going to do a REQUEST_SENSE 	 * automatically.  Note that we differentiate between a command	 * "failure" and an "error" in the transport mechanism.	 */	if (result == USB_STOR_TRANSPORT_FAILED) {			need_auto_sense = 1;	}	/*	 * A short transfer on a command where we don't expect it	 * is unusual, but it doesn't mean we need to auto-sense.	 */	if ((srb->resid > 0) &&	    !((srb->cmnd[0] == REQUEST_SENSE) ||	      (srb->cmnd[0] == INQUIRY) ||	      (srb->cmnd[0] == MODE_SENSE) ||	      (srb->cmnd[0] == LOG_SENSE) ||	      (srb->cmnd[0] == MODE_SENSE_10))) {		}	/* Now, if we need to do the auto-sense, let's do it */	if (need_auto_sense) {		int temp_result;		void* old_request_buffer;		unsigned short old_sg;		unsigned old_request_bufflen;		unsigned char old_sc_data_direction;		unsigned char old_cmd_len;		unsigned char old_cmnd[MAX_COMMAND_SIZE];		int old_resid;			/* save the old command */		memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE);		old_cmd_len = srb->cmd_len;		/* set the command and the LUN */		memset(srb->cmnd, 0, MAX_COMMAND_SIZE);		srb->cmnd[0] = REQUEST_SENSE;		srb->cmnd[1] = old_cmnd[1] & 0xE0;		srb->cmnd[4] = 18;			srb->cmd_len = 12;		/* set the transfer direction */		old_sc_data_direction = srb->sc_data_direction;		srb->sc_data_direction = DMA_FROM_DEVICE;		/* use the new buffer we have */		old_request_buffer = srb->request_buffer;		srb->request_buffer = us->sensebuf;		/* set the buffer length for transfer */		old_request_bufflen = srb->request_bufflen;		srb->request_bufflen = US_SENSE_SIZE;		/* set up for no scatter-gather use */		old_sg = srb->use_sg;		srb->use_sg = 0;		/* issue the auto-sense command */		old_resid = srb->resid;		srb->resid = 0;		temp_result = usb_stor_Bulk_transport(us->srb, us);		/* let's clean up right away */		memcpy(srb->sense_buffer, us->sensebuf, US_SENSE_SIZE);		srb->resid = old_resid;		srb->request_buffer = old_request_buffer;		srb->request_bufflen = old_request_bufflen;		srb->use_sg = old_sg;		srb->sc_data_direction = old_sc_data_direction;		srb->cmd_len = old_cmd_len;		memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE);		if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {						srb->result = DID_ABORT << 16;			goto Handle_Errors;		}		if (temp_result != USB_STOR_TRANSPORT_GOOD) {					/* we skip the reset if this happens to be a			 * multi-target device, since failure of an			 * auto-sense is perfectly valid			 */			srb->result = DID_ERROR << 16;			if (!(us->flags & US_FL_SCM_MULT_TARG))				goto Handle_Errors;			return;		}			/* set the result so the higher layers expect this data */		srb->result = SAM_STAT_CHECK_CONDITION;		/* If things are really okay, then let's show that.  Zero		 * out the sense buffer so the higher layers won't realize		 * we did an unsolicited auto-sense. */		if (result == USB_STOR_TRANSPORT_GOOD &&			/* Filemark 0, ignore EOM, ILI 0, no sense */				(srb->sense_buffer[2] & 0xaf) == 0 &&			/* No ASC or ASCQ */				srb->sense_buffer[12] == 0 &&				srb->sense_buffer[13] == 0) {			srb->result = SAM_STAT_GOOD;			srb->sense_buffer[0] = 0x0;		}	}	/* Did we transfer less than the minimum amount required? */	if (srb->result == SAM_STAT_GOOD &&			srb->request_bufflen - srb->resid < srb->underflow)		srb->result = (DID_ERROR << 16) | (SUGGEST_RETRY << 24);	return;	/* Error and abort processing: try to resynchronize with the device	 * by issuing a port reset.  If that fails, try a class-specific	 * device reset. */  Handle_Errors:	/* Set the RESETTING bit, and clear the ABORTING bit so that	 * the reset may proceed. */	scsi_lock(us_to_host(us));	set_bit(US_FLIDX_RESETTING, &us->flags);	clear_bit(US_FLIDX_ABORTING, &us->flags);	scsi_unlock(us_to_host(us));	/* We must release the device lock because the pre_reset routine	 * will want to acquire it. */	mutex_unlock(&us->dev_mutex);	result = usb_stor_port_reset(us);	mutex_lock(&us->dev_mutex);	if (result < 0) {		scsi_lock(us_to_host(us));		usb_stor_report_device_reset(us);		scsi_unlock(us_to_host(us));		usb_stor_Bulk_reset(us);	}	clear_bit(US_FLIDX_RESETTING, &us->flags);}static void usb_stor_stop_transport(struct us_data *us){	/* If the state machine is blocked waiting for an URB,	* let's wake it up.  The test_and_clear_bit() call	* guarantees that if a URB has just been submitted,	* it won't be cancelled more than once. */	if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) {		usb_unlink_urb(us->current_urb);	}	/* If we are waiting for a scatter-gather operation, cancel it. */	if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) {		usb_sg_cancel(&us->current_sg);	}}static int usb_worker(void * __us){	struct us_data *us = (struct us_data *)__us;	struct Scsi_Host *host = us_to_host(us);	current->flags |= PF_NOFREEZE;	for(;;) {		if(down_interruptible(&us->sema))			break;		/* lock the device pointers */		mutex_lock(&(us->dev_mutex));		/* if the device has disconnected, we are free to exit */		if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {			mutex_unlock(&us->dev_mutex);			break;		}		/* lock access to the state */		scsi_lock(host);		/* has the command timed out *already* ? */		if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {			us->srb->result = DID_ABORT << 16;			goto SkipForAbort;

⌨️ 快捷键说明

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