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

📄 csk_udisk_mgr.c

📁 linux 2.6.13 USB2.0开发补丁,lyj_uptech@126.com
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *		UDISK Driver For SUMSUNG Mobile *		BY CSK *		 *		SPECIAL THX TO Michael Gee (michael@linuxspecific.com) *///Something to be include...#include <linux/sched.h>#include <linux/errno.h>#include <linux/freezer.h>#include <linux/module.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/kthread.h>#include <linux/mutex.h>#include <linux/utsrelease.h>#include <linux/usb.h>#include <linux/usb_usual.h>#include <linux/blkdev.h>#include <linux/smp_lock.h>#include <linux/completion.h>#include <linux/mutex.h>#include <linux/slab.h>#include <linux/highmem.h>//SCSI support#include <scsi/scsi.h>#include <scsi/scsi_cmnd.h>#include <scsi/scsi_devinfo.h>#include <scsi/scsi_device.h>#include <scsi/scsi_host.h>#include <scsi/scsi_eh.h>#include <asm/scatterlist.h>#include <asm/dma.h> // I hate this guy...struct us_data;struct scsi_cmnd;/* command block wrapper */struct bulk_cb_wrap {	__le32	Signature;		/* contains 'USBC' */	__u32	Tag;			/* unique per command id */	__le32	DataTransferLength;	/* size of data */	__u8	Flags;			/* direction in bit 0 */	__u8	Lun;			/* LUN normally 0 */	__u8	Length;			/* of of the CDB */	__u8	CDB[16];		/* max command */};#define US_BULK_CB_WRAP_LEN	31#define US_BULK_CB_SIGN		0x43425355	/*spells out USBC */#define US_BULK_FLAG_IN		1#define US_BULK_FLAG_OUT	0/* command status wrapper */struct bulk_cs_wrap {	__le32	Signature;		/* should = 'USBS' */	__u32	Tag;			/* same as original command */	__le32	Residue;		/* amount not transferred */	__u8	Status;			/* see below */	__u8	Filler[18];};#define US_BULK_CS_WRAP_LEN	13#define US_BULK_CS_SIGN		0x53425355	/* spells out 'USBS' */#define US_BULK_STAT_OK		0#define US_BULK_STAT_FAIL	1#define US_BULK_STAT_PHASE	2/* bulk-only class specific requests */#define US_BULK_RESET_REQUEST	0xff#define US_BULK_GET_MAX_LUN	0xfe#define USB_STOR_XFER_GOOD	0	/* good transfer                 */#define USB_STOR_XFER_SHORT	1	/* transferred less than expected */#define USB_STOR_XFER_STALLED	2	/* endpoint stalled              */#define USB_STOR_XFER_LONG	3	/* device tried to send too much */#define USB_STOR_XFER_ERROR	4	/* transfer died in the middle   *//* * Transport return codes */#define USB_STOR_TRANSPORT_GOOD	   0   /* Transport good, command good	   */#define USB_STOR_TRANSPORT_FAILED  1   /* Transport good, command failed   */#define USB_STOR_TRANSPORT_NO_SENSE 2  /* Command failed, no auto-sense    */#define USB_STOR_TRANSPORT_ERROR   3   /* Transport bad (i.e. device dead) *//* Dynamic flag definitions: used in set_bit() etc. */#define US_FLIDX_URB_ACTIVE	18  /* 0x00040000  current_urb is in use  */#define US_FLIDX_SG_ACTIVE	19  /* 0x00080000  current_sg is in use   */#define US_FLIDX_ABORTING	20  /* 0x00100000  abort is in progress   */#define US_FLIDX_DISCONNECTING	21  /* 0x00200000  disconnect in progress */#define ABORTING_OR_DISCONNECTING	((1UL << US_FLIDX_ABORTING) | \					 (1UL << US_FLIDX_DISCONNECTING))#define US_FLIDX_RESETTING	22  /* 0x00400000  device reset in progress */#define US_FLIDX_TIMED_OUT	23  /* 0x00800000  SCSI midlayer timed out  */#define USB_STOR_STRING_LEN 32#define US_IOBUF_SIZE		64	/* Size of the DMA-mapped I/O buffer */#define US_SENSE_SIZE		18	/* Size of the autosense data buffer */#define US_SUSPEND	0#define US_RESUME	1/* 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)/* we allocate one of these for every device that we remember */struct us_data {	struct mutex		dev_mutex;	 /* protect pusb_dev */	struct usb_device	*pusb_dev;	 /* this usb_device */	struct usb_interface	*pusb_intf;	 /* this interface */	unsigned long		flags;		 /* from filter initially */	unsigned int		send_bulk_pipe;	 /* cached pipe values */	unsigned int		recv_bulk_pipe;	unsigned int		send_ctrl_pipe;	unsigned int		recv_ctrl_pipe;	unsigned int		recv_intr_pipe;	/* informatioscsi_report_bus_reset(us_to_host(us), 0);n about the device */	__le32			bcs_signature;	u8			subclass;	u8			protocol;	u8			max_lun;	u8			ifnum;		 /* interface number   */	u8			ep_bInterval;	 /* interrupt interval */ 		/* SCSI interfaces */	struct scsi_cmnd	*srb;		 /* current srb		*/	unsigned int		tag;		 /* current dCBWTag	*/	/* control and bulk communications data */	struct urb		*current_urb;	 /* USB requests	 */	struct usb_ctrlrequest	*cr;		 /* control requests	 */	struct usb_sg_request	current_sg;	 /* scatter-gather req.  */	unsigned char		*iobuf;		 /* I/O buffer		 */	unsigned char		*sensebuf;	 /* sense data buffer	 */	dma_addr_t		cr_dma;		 /* buffer DMA addresses */	dma_addr_t		iobuf_dma;	/* mutual exclusion and synchronization structures */	struct semaphore	sema;		 /* to sleep thread on	    */	struct completion	notify;		 /* thread begin/end	    */	wait_queue_head_t	delay_wait;	 /* wait during scan, reset */};static inline struct Scsi_Host *us_to_host(struct us_data *us) {	return container_of((void *) us, struct Scsi_Host, hostdata);}static inline struct us_data *host_to_us(struct Scsi_Host *host) {	return (struct us_data *) host->hostdata;}#define scsi_unlock(host)	spin_unlock_irq(host->host_lock)#define scsi_lock(host)		spin_lock_irq(host->host_lock)MODULE_AUTHOR("CSK");MODULE_DESCRIPTION("SAMSUNG MOBILE USB Mass Storage");MODULE_LICENSE("GPL");static atomic_t g_total_workers = ATOMIC_INIT(0);//SAMSUNG MOBILE USB INFO#define USB_MASS_VENDOR_ID	0x04e8#define USB_MASS_PRODUCT_ID	0x665c	//REG ITstatic struct usb_device_id storage_usb_ids [] = {	{ USB_DEVICE(USB_MASS_VENDOR_ID, USB_MASS_PRODUCT_ID) },		{ }					/* Terminating entry */};MODULE_DEVICE_TABLE (usb, storage_usb_ids);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 */};//PROTOTYPEstatic int usb_worker(void * __us);static void FreeUpAll(struct us_data *us);static void quiesce_and_remove_host(struct us_data *us);static void usb_stor_stop_transport(struct us_data *us);static int usb_stor_clear_halt(struct us_data *us, unsigned int pipe);static void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us);static int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us);static int usb_stor_port_reset(struct us_data *us);static void usb_stor_report_device_reset(struct us_data *us);static int usb_stor_Bulk_reset(struct us_data *us);static int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,	void *buf, unsigned int length, unsigned int *act_len);static int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe,		void *buf, unsigned int length_left, int use_sg, int *residual);static int usb_stor_control_msg(struct us_data *us, unsigned int pipe,		 u8 request, u8 requesttype, u16 value, u16 index, 		 void *data, u16 size, int timeout);static int usb_stor_msg_common(struct us_data *us, int timeout);static int interpret_urb_result(struct us_data *us, unsigned int pipe,		unsigned int length, int result, unsigned int partial);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);static int usb_stor_Bulk_max_lun(struct us_data *us);static void usb_stor_blocking_completion(struct urb *urb);static int slave_configure(struct scsi_device *sdev);static int slave_alloc (struct scsi_device *sdev);static int bus_reset(struct scsi_cmnd *srb);static int device_reset(struct scsi_cmnd *srb);static int command_abort(struct scsi_cmnd *srb);static int queuecommand(struct scsi_cmnd *srb,			void (*done)(struct scsi_cmnd *));static const char* host_info(struct Scsi_Host *host);static int proc_info (struct Scsi_Host *host, char *buffer,		char **start, off_t offset, int length, int inout);static ssize_t store_max_sectors(struct device *dev, struct device_attribute *attr, const char *buf,		size_t count);static ssize_t show_max_sectors(struct device *dev, struct device_attribute *attr, char *buf);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,		};struct scsi_host_template usb_stor_host_template = {	/* basic userland interface stuff */	.name =				"mobileusb-storage",	.proc_name =			"mobileusb-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};///static void storage_pre_reset(struct usb_interface *iface){	struct us_data *us = usb_get_intfdata(iface);	/* Make sure no command runs during the reset */	mutex_lock(&us->dev_mutex);}static void storage_post_reset(struct usb_interface *iface){	struct us_data *us = usb_get_intfdata(iface);	/* Report the reset to the SCSI core */	scsi_lock(us_to_host(us));	scsi_report_bus_reset(us_to_host(us), 0);	scsi_unlock(us_to_host(us));	/* FIXME: Notify the subdrivers that they need to reinitialize	* the device */	mutex_unlock(&us->dev_mutex);}//Begin working...static int storage_probe(struct usb_interface *intf,						 const struct usb_device_id *id){	struct Scsi_Host *host;	struct us_data *us;	int Ans;	struct task_struct *th;	int i;	struct usb_endpoint_descriptor *ep;	struct usb_endpoint_descriptor *ep_in = NULL;	struct usb_endpoint_descriptor *ep_out = NULL;	struct usb_endpoint_descriptor *ep_int = NULL;	/*	* Ask the SCSI layer to allocate a host structure, with extra	* space at the end for our private us_data structure.	*/	host = scsi_host_alloc(&usb_stor_host_template, sizeof(*us));	if (!host) {		printk(KERN_WARNING	"allocate the scsi host failed\n");		return -ENOMEM;	}	us = host_to_us(host);	memset(us, 0, sizeof(struct us_data));	mutex_init(&(us->dev_mutex));	init_MUTEX_LOCKED(&(us->sema));	init_completion(&(us->notify));	init_waitqueue_head(&us->delay_wait);	/* Associate the us_data structure with the USB device */	/* Fill in the device-related fields */	us->pusb_dev = interface_to_usbdev(intf);	us->pusb_intf = intf;	us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;	/* Store our private data in the interface */	usb_set_intfdata(intf, us);	/* Allocate the device-related DMA-mapped buffers */	us->cr = usb_buffer_alloc(us->pusb_dev, sizeof(*us->cr),		GFP_KERNEL, &us->cr_dma);	if (!us->cr) {		goto BadDevice;	}	us->iobuf = usb_buffer_alloc(us->pusb_dev, US_IOBUF_SIZE,		GFP_KERNEL, &us->iobuf_dma);	if (!us->iobuf) {		goto BadDevice;	}	us->sensebuf = kmalloc(US_SENSE_SIZE, GFP_KERNEL);	if (!us->sensebuf) {		goto BadDevice;	}	us->subclass =	us->pusb_intf->cur_altsetting->desc.bInterfaceSubClass;		us->protocol =  us->pusb_intf->cur_altsetting->desc.bInterfaceProtocol ;	us->flags = USB_US_ORIG_FLAGS(id->driver_info);	if (us->flags & US_FL_IGNORE_DEVICE) {		printk(KERN_INFO "device ignored\n");		goto BadDevice;	}	/*	* This flag is only needed when we're in high-speed, so let's	* disable it if we're in full-speed	*/	if (us->pusb_dev->speed != USB_SPEED_HIGH)		us->flags &= ~US_FL_GO_SLOW;	/* Get the transport, protocol, and pipe settings */	if (us->protocol != US_PR_BULK){		printk(KERN_INFO "device mismatched\n");		goto BadDevice;		}		if (us->subclass != US_SC_8020){		printk(KERN_INFO "device mismatched\n");		goto BadDevice;		}	us->max_lun = 0;	/*	* Find the endpoints we need.	* We are expecting a minimum of 2 endpoints - in and out (bulk).	* An optional interrupt is OK (necessary for CBI protocol).	* We will ignore any others.	*/	for (i = 0; i < us->pusb_intf->cur_altsetting->desc.bNumEndpoints; i++) {		ep = &us->pusb_intf->cur_altsetting->endpoint[i].desc;		/* Is it a BULK endpoint? */		if (usb_endpoint_xfer_bulk(ep)) {			/* BULK in or out? */			if (usb_endpoint_dir_in(ep))

⌨️ 快捷键说明

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