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

📄 usb-storage.c

📁 Usb1.1驱动c语言源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	case US_PR_CBI:		/* get from interrupt pipe */		/* add interrupt transfer, marked for removal */		us->ip_wanted = 1;		/* go to sleep until we get this interrup */		/* FIXME: this should be changed to use a timeout */		sleep_on(&us->ip_waitq);    		if (us->ip_wanted) {			US_DEBUGP("Did not get interrupt on CBI\n");			us->ip_wanted = 0;			return USB_STOR_TRANSPORT_ERROR;		}    		US_DEBUGP("Got interrupt data 0x%x\n", us->ip_data);		/* UFI gives us ASC and ASCQ, like a request sense */		/* FIXME: is this right?  do REQUEST_SENSE and INQUIRY need special		 * case handling?		 */		if (us->subclass == US_SC_UFI) {			if (srb->cmnd[0] == REQUEST_SENSE ||			    srb->cmnd[0] == INQUIRY)				return USB_STOR_TRANSPORT_GOOD;			else				if (us->ip_data)					return USB_STOR_TRANSPORT_FAILED;				else					return USB_STOR_TRANSPORT_GOOD;		}		/* otherwise, we interpret the data normally */		switch (us->ip_data) {		case 0x0001: 			return USB_STOR_TRANSPORT_GOOD;		case 0x0002: 			return USB_STOR_TRANSPORT_FAILED;		default: 			return USB_STOR_TRANSPORT_ERROR;		}	}	US_DEBUGP("pop_CB_status, reached end of function\n");	return USB_STOR_TRANSPORT_ERROR;}static int Bulk_reset(struct us_data *us){	int result;	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),				 US_BULK_RESET, USB_TYPE_CLASS | USB_RECIP_INTERFACE,				 US_BULK_RESET_HARD, us->ifnum,				 NULL, 0, HZ*5);	if (result)		US_DEBUGP("Bulk hard reset failed %d\n", result);	usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));	usb_clear_halt(us->pusb_dev, usb_sndbulkpipe(us->pusb_dev, us->ep_out));	/* long wait for reset */	schedule_timeout(HZ*6);	return result;}/* * The bulk only protocol handler. *	Uses the in and out endpoints to transfer commands and data */static int Bulk_transport(Scsi_Cmnd *srb, struct us_data *us){	struct bulk_cb_wrap bcb;	struct bulk_cs_wrap bcs;	int result;	int pipe;	int partial;	/* set up the command wrapper */	bcb.Signature = US_BULK_CB_SIGN;	bcb.DataTransferLength = us_transfer_length(srb);	bcb.Flags = US_DIRECTION(srb->cmnd[0]) << 7;	bcb.Tag = srb->serial_number;	bcb.Lun = 0;	bcb.Length = srb->cmd_len;	/* construct the pipe handle */	pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);	/* copy the command payload */	memset(bcb.CDB, 0, sizeof(bcb.CDB));	memcpy(bcb.CDB, srb->cmnd, bcb.Length);	/* send it to out endpoint */	US_DEBUGP("Bulk command S 0x%x T 0x%x L %d F %d CL %d\n",		  bcb.Signature, bcb.Tag, bcb.DataTransferLength,		  bcb.Flags, bcb.Length);	result = usb_bulk_msg(us->pusb_dev, pipe, &bcb,			      US_BULK_CB_WRAP_LEN, &partial, HZ*5);	US_DEBUGP("Bulk command transfer result=%d\n", result);	/* if we stall, we need to clear it before we go on */	if (result == -EPIPE) {		US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);		usb_clear_halt(us->pusb_dev, pipe);	}  	/* if the command transfered well, then we go to the data stage */	/* FIXME: Regardless of the status of the data stage, we go on to the	 * status stage.  Note that this implies that if a command is	 * partially successful, we rely on the device reporting an error	 * the CSW. The spec says that the device may just decide to short us.	 */	if (result == 0) {		/* send/receive data payload, if there is any */		if (bcb.DataTransferLength) {			result = us_transfer(srb, bcb.Flags);			US_DEBUGP("Bulk data transfer result 0x%x\n", result);#if 0			if ((result < 0) && (result != USB_ST_DATAUNDERRUN) 			    && (result != USB_ST_STALL)) {				US_DEBUGP("Bulk data transfer result 0x%x\n", result);				return DID_ABORT << 16;			}#endif		}	}	/* See flow chart on pg 15 of the Bulk Only Transport spec for	 * an explanation of how this code works.	 */	/* construct the pipe handle */	pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);	/* get CSW for device status */	result = usb_bulk_msg(us->pusb_dev, pipe, &bcs,			      US_BULK_CS_WRAP_LEN, &partial, HZ*5);	/* did the attempt to read the CSW fail? */	if (result == -EPIPE) {		US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);		usb_clear_halt(us->pusb_dev, pipe);		/* get the status again */		result = usb_bulk_msg(us->pusb_dev, pipe, &bcs,				      US_BULK_CS_WRAP_LEN, &partial, HZ*5);   		/* if it fails again, we need a reset and return an error*/		if (result == -EPIPE) {			Bulk_reset(us);			return (DID_ABORT << 16);		}	}	/* if we still have a failure at this point, we're in trouble */	if (result) {		US_DEBUGP("Bulk status result = 0x%x\n", result);		return DID_ABORT << 16;	}	/* check bulk status */	US_DEBUGP("Bulk status S 0x%x T 0x%x R %d V 0x%x\n",		  bcs.Signature, bcs.Tag, bcs.Residue, bcs.Status);	if (bcs.Signature != US_BULK_CS_SIGN || bcs.Tag != bcb.Tag ||	    bcs.Status > US_BULK_STAT_PHASE || partial != 13) {		US_DEBUGP("Bulk logical error\n");		return DID_ABORT << 16;	}	/* based on the status code, we report good or bad */	switch (bcs.Status) {	case US_BULK_STAT_OK:		/* if there is residue, we really didn't finish the command */		if (bcs.Residue)			return DID_ERROR << 16;		else			return DID_OK << 16;	case US_BULK_STAT_FAIL:		return DID_ERROR << 16;	case US_BULK_STAT_PHASE:		Bulk_reset(us);		return DID_ERROR << 16;	}	return DID_OK << 16;	    /* check sense required */}/*********************************************************************** * Host functions  ***********************************************************************//* detect adapter (always true ) */static int us_detect(struct SHT *sht){	/* FIXME - not nice at all, but how else ? */	struct us_data *us = (struct us_data *)sht->proc_dir;	char name[32];	/* set up our name */	sprintf(name, "usbscsi%d", us->host_number);	sht->name = sht->proc_name = kmalloc(strlen(name)+1, GFP_KERNEL);	if (!sht->proc_name)		return 0;	strcpy(sht->proc_name, name);	/* we start with no /proc directory entry */	sht->proc_dir = NULL;	/* register the host */	us->host = scsi_register(sht, sizeof(us));	if (us->host) {		us->host->hostdata[0] = (unsigned long)us;		us->host_no = us->host->host_no;		return 1;	}	/* odd... didn't register properly.  Abort and free pointers */	kfree(sht->proc_name);	sht->proc_name = NULL;	sht->name = NULL;	return 0;}/* release - must be here to stop scsi *	from trying to release IRQ etc. *	Kill off our data */static int us_release(struct Scsi_Host *psh){	struct us_data *us = (struct us_data *)psh->hostdata[0];	struct us_data *prev = (struct us_data *)&us_list;	if (us->irq_handle) {		usb_release_irq(us->pusb_dev, us->irq_handle, us->irqpipe);		us->irq_handle = NULL;	}	if (us->pusb_dev)		usb_deregister(&storage_driver);	/* FIXME - leaves hanging host template copy */	/* (because scsi layer uses it after removal !!!) */	while (prev->next != us)		prev = prev->next;	prev->next = us->next;	return 0;}/* run command */static int us_command( Scsi_Cmnd *srb ){	US_DEBUGP("Bad use of us_command\n");	return DID_BAD_TARGET << 16;}/* run command */static int us_queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *)){	struct us_data *us = (struct us_data *)srb->host->hostdata[0];	US_DEBUGP("Command wakeup\n");	if (us->srb) {		/* busy */	}	srb->host_scribble = (unsigned char *)us;	us->srb = srb;	srb->scsi_done = done;	us->action = US_ACT_COMMAND;	/* wake up the process task */	wake_up_interruptible(&us->waitq);	return 0;}/* FIXME: This doesn't actually abort anything */static int us_abort( Scsi_Cmnd *srb ){	return 0;}static int us_bus_reset( Scsi_Cmnd *srb ){	//  struct us_data *us = (struct us_data *)srb->host->hostdata[0];	US_DEBUGP("Bus reset requested\n");	//  us->transport_reset(us);	return SUCCESS;}/* FIXME: This doesn't actually reset anything */static int us_host_reset( Scsi_Cmnd *srb ){	return 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)int usb_stor_proc_info (char *buffer, char **start, off_t offset, 			int length, int hostno, int inout){	struct us_data *us = us_list;	char *pos = buffer;	char *tmp_ptr;	/* find our data from hostno */	while (us) {		if (us->host_no == hostno)			break;		us = us->next;	}	/* if we couldn't find it, we return an error */	if (!us)		return -ESRCH;	/* if someone is sending us data, just throw it away */	if (inout)		return length;	/* print the controler name */	SPRINTF ("Host scsi%d: usb-storage\n", hostno);	/* print product and vendor strings */	tmp_ptr = kmalloc(256, GFP_KERNEL);	if (!us->pusb_dev || !tmp_ptr) {		SPRINTF("    Vendor: Unknown Vendor\n");		SPRINTF("   Product: Unknown Product\n");	} else {		SPRINTF("    Vendor: ");		if (usb_string(us->pusb_dev, us->pusb_dev->descriptor.iManufacturer, tmp_ptr, 256) > 0)			SPRINTF("%s\n", tmp_ptr);		else			SPRINTF("Unknown Vendor\n");    		SPRINTF("   Product: ");		if (usb_string(us->pusb_dev, us->pusb_dev->descriptor.iProduct, tmp_ptr, 256) > 0)			SPRINTF("%s\n", tmp_ptr);		else			SPRINTF("Unknown Product\n");		kfree(tmp_ptr);	}	SPRINTF("  Protocol: ");	switch (us->protocol) {	case US_PR_CB:		SPRINTF("Control/Bulk\n");		break;    	case US_PR_CBI:		SPRINTF("Control/Bulk/Interrupt\n");		break;    	case US_PR_BULK:		SPRINTF("Bulk only\n");		break;    	default:		SPRINTF("Unknown Protocol\n");		break;	}	/* show the GUID of the device */	SPRINTF("      GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid));	/*	 * 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);}/* * this defines our 'host' */static Scsi_Host_Template my_host_template = {	NULL,			    /* next */	NULL,			    /* module */	NULL,			    /* proc_dir */	usb_stor_proc_info,	NULL,			    /* name - points to unique */	us_detect,	us_release,	NULL,			    /* info */	NULL,			    /* ioctl */	us_command,	us_queuecommand,	NULL,			    /* eh_strategy */	us_abort,	us_bus_reset,	us_bus_reset,	us_host_reset,	NULL,			    /* abort */	NULL,			    /* reset */	NULL,			    /* slave_attach */	NULL,			    /* bios_param */	NULL,			    /* select_queue_depths */	1,			    /* can_queue */	-1,			    /* this_id */	SG_ALL,		    /* sg_tablesize */	1,			    /* cmd_per_lun */	0,			    /* present */	FALSE,		    /* unchecked_isa_dma */	FALSE,		    /* use_clustering */	TRUE,			    /* use_new_eh_code */	TRUE			    /* emulated */};static unsigned char sense_notready[] = {	0x70,			    /* current error */	0x00,	0x02,			    /* not ready */	0x00,	0x00,	0x0a,			    /* additional length */	0x00,	0x00,	0x00,	0x00,	0x04,			    /* not ready */	0x03,			    /* manual intervention */	0x00,	0x00,	0x00,	0x00};static int usb_stor_control_thread(void * __us){	struct us_data *us = (struct us_data *)__us;	int action;	lock_kernel();	/*	 * This thread doesn't need any user-level access,	 * so get rid of all our resources..	 */	daemonize();	sprintf(current->comm, "usbscsi%d", us->host_number);	unlock_kernel();	up(us->notify);

⌨️ 快捷键说明

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