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

📄 usb-storage.c

📁 Usb1.1驱动c语言源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	 * REQUEST_SENSE --  either way, this belongs at a higher level	 */#if 0	/* For UFI, if this is the first time we've sent this TEST_UNIT_READY 	 * command, we can try again	 */	if (!done_start && (us->subclass == US_SC_UFI)	    && (cmd[0] == TEST_UNIT_READY) && (result < 0)) {    		/* as per spec try a start command, wait and retry */		wait_ms(100);    		done_start++;		memset(cmd, 0, sizeof(cmd));		cmd[0] = START_STOP;		cmd[4] = 1;		/* start */    		result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),					 US_CBI_ADSC, 					 USB_TYPE_CLASS | USB_RECIP_INTERFACE,					 0, us->ifnum,					 cmd, 12, HZ*5);		US_DEBUGP("Next usb_control_msg returns %d\n", result);    				/* allow another retry */		retry++;		continue;	}#endif}static void transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us){	unsigned int savelen = us->srb->request_bufflen;	unsigned int saveallocation = 0;#if 0	/* force attention on first command */	if (!us->attention_done) {		if (us->srb->cmnd[0] == REQUEST_SENSE) {			US_DEBUGP("forcing unit attention\n");			us->attention_done = 1;			if (us->srb->result == USB_STOR_TRANSPORT_GOOD) {				unsigned char *p = (unsigned char *)us->srb->request_buffer;					if ((p[2] & 0x0f) != UNIT_ATTENTION) {					p[2] = UNIT_ATTENTION;					p[12] = 0x29;	/* power on, reset or bus-reset */					p[13] = 0;				} /* if ((p[2] & 0x0f) != UNIT_ATTENTION) */			} /* if (us->srb->result == USB_STORE_TRANSPORT_GOOD) */		}	} /* if (!us->attention_done) */#endif	/* If the command has a variable-length payload, then we do them	 * in two steps -- first we do the minimum, then we recalculate	 * then length, and re-issue the command 	 *	 * we use savelen to remember how much buffer we really have	 * we use savealloction to remember how much was really requested	 */	/* FIXME: remove savelen based on mods to us_transfer_length() */	switch (us->srb->cmnd[0]) {	case REQUEST_SENSE:		if (us->srb->request_bufflen > 18)			us->srb->request_bufflen = 18;		else			break;		saveallocation = us->srb->cmnd[4];		us->srb->cmnd[4] = 18;		break;    	case INQUIRY:		if (us->srb->request_bufflen > 36)			us->srb->request_bufflen = 36;		else			break;		saveallocation = us->srb->cmnd[4];		us->srb->cmnd[4] = 36;		break;    	case MODE_SENSE:		if (us->srb->request_bufflen > 4)			us->srb->request_bufflen = 4;		else			break;		saveallocation = us->srb->cmnd[4];		us->srb->cmnd[4] = 4;		break;    	case LOG_SENSE:	case MODE_SENSE_10:		if (us->srb->request_bufflen > 8)			us->srb->request_bufflen = 8;		else			break;		saveallocation = (us->srb->cmnd[7] << 8) | us->srb->cmnd[8];		us->srb->cmnd[7] = 0;		us->srb->cmnd[8] = 8;		break;    	default:		break;	} /* end switch on cmnd[0] */  	/* This code supports devices which do not support {READ|WRITE}_6	 * Apparently, neither Windows or MacOS will use these commands,	 * so some devices do not support them	 */	if (us->flags & US_FL_MODE_XLATE) {    		/* translate READ_6 to READ_10 */		if (us->srb->cmnd[0] == 0x08) {      			/* get the control */			us->srb->cmnd[9] = us->srb->cmnd[5];      			/* get the length */			us->srb->cmnd[8] = us->srb->cmnd[6];			us->srb->cmnd[7] = 0;      			/* set the reserved area to 0 */			us->srb->cmnd[6] = 0;	          			/* get LBA */			us->srb->cmnd[5] = us->srb->cmnd[3];			us->srb->cmnd[4] = us->srb->cmnd[2];			us->srb->cmnd[3] = 0;			us->srb->cmnd[2] = 0;      			/* LUN and other info in cmnd[1] can stay */      			/* fix command code */			us->srb->cmnd[0] = 0x28;      			US_DEBUGP("Changing READ_6 to READ_10\n");			US_DEBUG(us_show_command(us->srb));		}    		/* translate WRITE_6 to WRITE_10 */		if (us->srb->cmnd[0] == 0x0A) {      			/* get the control */			us->srb->cmnd[9] = us->srb->cmnd[5];      			/* get the length */			us->srb->cmnd[8] = us->srb->cmnd[4];			us->srb->cmnd[7] = 0;      			/* set the reserved area to 0 */			us->srb->cmnd[6] = 0;	          			/* get LBA */			us->srb->cmnd[5] = us->srb->cmnd[3];			us->srb->cmnd[4] = us->srb->cmnd[2];			us->srb->cmnd[3] = 0;			us->srb->cmnd[2] = 0;	    			/* LUN and other info in cmnd[1] can stay */      			/* fix command code */			us->srb->cmnd[0] = 0x2A;			US_DEBUGP("Changing WRITE_6 to WRITE_10\n");			US_DEBUG(us_show_command(us->srb));		}	} /* end if (us->flags & US_FL_MODE_XLATE) */  	/* send the command to the transport layer */	us->srb->result = us->transport(us->srb, us);	/* if we have an error, we're going to do a REQUEST_SENSE 	 * automatically */	/* FIXME: we should only do this for device errors, not 	 * system errors */	if (us->srb->result) {		int temp_result;		int count;		void* old_request_buffer;		US_DEBUGP("Command FAILED: Issuing auto-REQUEST_SENSE\n");		/* set the result so the higher layers expect this data */		us->srb->result = CHECK_CONDITION;		us->srb->cmnd[0] = REQUEST_SENSE;		us->srb->cmnd[1] = 0;		us->srb->cmnd[2] = 0;		us->srb->cmnd[3] = 0;		us->srb->cmnd[4] = 18;		us->srb->cmnd[5] = 0;    		/* set the buffer length for transfer */		old_request_buffer = us->srb->request_buffer;		us->srb->request_bufflen = 18;		us->srb->request_buffer = kmalloc(18, GFP_KERNEL);		/* FIXME: what if this command fails? */		temp_result = us->transport(us->srb, us);		US_DEBUGP("-- Result from auto-sense is %d\n", temp_result);		/* copy the data from the request buffer to the sense buffer */		for(count = 0; count < 18; count++)			us->srb->sense_buffer[count] = 				((unsigned char *)(us->srb->request_buffer))[count];		US_DEBUGP("-- sense key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",			  us->srb->sense_buffer[2] & 0xf,			  us->srb->sense_buffer[12], us->srb->sense_buffer[13]);		/* we're done here */		kfree(us->srb->request_buffer);		us->srb->request_buffer = old_request_buffer;		return;	}	if (savelen != us->srb->request_bufflen) {		unsigned char *p = (unsigned char *)us->srb->request_buffer;		unsigned int length = 0;    		/* set correct length and retry */		switch (us->srb->cmnd[0]) {			/* FIXME: we should try to get all the sense data */		case REQUEST_SENSE:			/* simply return 18 bytes */			p[7] = 10;			length = us->srb->request_bufflen;			break;      		case INQUIRY:			length = p[4] + 5 > savelen ? savelen : p[4] + 5;			us->srb->cmnd[4] = length;			break;      		case MODE_SENSE:			US_DEBUGP("MODE_SENSE Mode data length is %d\n", p[0]);			length = p[0] + 1 > savelen ? savelen : p[0] + 1;			us->srb->cmnd[4] = length;			break;      		case LOG_SENSE:			length = ((p[2] << 8) + p[3]) + 4 > savelen ? savelen : ((p[2] << 8) + p[3]) + 4;			us->srb->cmnd[7] = length >> 8;			us->srb->cmnd[8] = length;			break;      		case MODE_SENSE_10:			US_DEBUGP("MODE_SENSE_10 Mode data length is %d\n",				  (p[0] << 8) + p[1]);			length = ((p[0] << 8) + p[1]) + 6 > savelen ? savelen : ((p[0] << 8) + p[1]) + 6;			us->srb->cmnd[7] = length >> 8;			us->srb->cmnd[8] = length;			break;		} /* end switch on cmnd[0] */    		US_DEBUGP("Old/New length = %d/%d\n",			  savelen, length);    		/* issue the new command */		/* FIXME: this assumes that the second attempt is 		 * always successful */		if (us->srb->request_bufflen != length) {			US_DEBUGP("redoing cmd with len=%d\n", length);			us->srb->request_bufflen = length;			us->srb->result = us->transport(us->srb, us);		}    		/* reset back to original values */		us->srb->request_bufflen = savelen;		/* fix data as necessary */		switch (us->srb->cmnd[0]) {		case INQUIRY:			if ((((unsigned char*)us->srb->request_buffer)[2] & 0x7) == 0) { 				US_DEBUGP("Fixing INQUIRY data, setting SCSI rev to 2\n");				((unsigned char*)us->srb->request_buffer)[2] |= 2;			}			/* FALL THROUGH */		case REQUEST_SENSE:		case MODE_SENSE:			if (us->srb->use_sg == 0 && length > 0) {				int i;				printk(KERN_DEBUG "Data is");				for (i = 0; i < 32 && i < length; ++i)					printk(" %.2x", ((unsigned char *)us->srb->request_buffer)[i]);				if (i < length)					printk(" ...");				printk("\n");			}			/* FIXME: is this really necessary? */			us->srb->cmnd[4] = saveallocation;			break;      		case LOG_SENSE:		case MODE_SENSE_10:			/* FIXME: is this really necessary? */			us->srb->cmnd[7] = saveallocation >> 8;			us->srb->cmnd[8] = saveallocation;			break;		} /* end switch on cmnd[0] */	} /* if good command */}/*********************************************************************** * Transport routines ***********************************************************************/static int CBI_irq(int state, void *buffer, int len, void *dev_id){	struct us_data *us = (struct us_data *)dev_id;	US_DEBUGP("USB IRQ recieved for device on host %d\n", us->host_no);	/* save the data for interpretation later */	if (state != USB_ST_REMOVED) {		us->ip_data = le16_to_cpup((__u16 *)buffer);		US_DEBUGP("Interrupt Status 0x%x\n", us->ip_data);	}  	/* was this a wanted interrupt? */	if (us->ip_wanted) {		us->ip_wanted = 0;		wake_up(&us->ip_waitq);	} else {		US_DEBUGP("ERROR: Unwanted interrupt received!\n");	}	/* This return code is truly meaningless -- and I mean truly.  It gets	 * ignored by other layers.  It used to indicate if we wanted to get	 * another interrupt or disable the interrupt callback	 */	return 0;}/* FIXME: this reset function doesn't really reset the port, and it * should. Actually it should probably do what it's doing here, and * reset the port physically */static int CB_reset(struct us_data *us){	unsigned char cmd[12];	int result;	US_DEBUGP("CB_reset\n");	memset(cmd, 0xFF, sizeof(cmd));	cmd[0] = SEND_DIAGNOSTIC;	cmd[1] = 4;	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),				 US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,				 0, us->ifnum, cmd, sizeof(cmd), HZ*5);	/* long wait for reset */	schedule_timeout(HZ*6);	US_DEBUGP("CB_reset: clearing endpoint halt\n");	usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));	usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));	US_DEBUGP("CB_reset done\n");	return 0;}static int pop_CB_status(Scsi_Cmnd *srb);/* FIXME: we also need a CBI_command which sets up the completion * interrupt, and waits for it */static int CB_transport(Scsi_Cmnd *srb, struct us_data *us){	int result;	US_DEBUGP("CBI gets a command:\n");	US_DEBUG(us_show_command(srb));	/* FIXME: we aren't setting the ip_wanted indicator early enough, which	 * causes some commands to never complete.  This hangs the driver.	 */	/* let's send the command via the control pipe */	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),				 US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,				 0, us->ifnum,				 srb->cmnd, srb->cmd_len, HZ*5);	/* check the return code for the command */	if (result < 0) {		US_DEBUGP("Call to usb_control_msg() returned %d\n", result);		/* a stall is a fatal condition from the device */		if (result == -EPIPE) {			US_DEBUGP("-- Stall on control pipe detected. Clearing\n");      			US_DEBUGP("-- Return from usb_clear_halt() is %d\n",				  usb_clear_halt(us->pusb_dev, 						 usb_sndctrlpipe(us->pusb_dev, 0)));			return USB_STOR_TRANSPORT_ERROR;		}		/* FIXME: we need to handle NAKs here */		return USB_STOR_TRANSPORT_ERROR;	}	/* transfer the data payload for this command, if one exists*/	if (us_transfer_length(srb)) {		result = us_transfer(srb, US_DIRECTION(srb->cmnd[0]));		US_DEBUGP("CBI attempted to transfer data, result is 0x%x\n", result);		/* FIXME: what do the return codes from us_transfer mean? */		if ((result < 0) && 		    (result != USB_ST_DATAUNDERRUN) && 		    (result != USB_ST_STALL)) {			return DID_ERROR << 16;		}	} /* if (us_transfer_length(srb)) */	/* get status and return it */	return pop_CB_status(srb);}/* * Control/Bulk status handler */static int pop_CB_status(Scsi_Cmnd *srb){	struct us_data *us = (struct us_data *)srb->host_scribble;	int result = 0;	__u8 status[2];	int retry = 5;	US_DEBUGP("pop_CB_status, proto=0x%x\n", us->protocol);	switch (us->protocol) {	case US_PR_CB:		/* get from control */		while (retry--) {			result = usb_control_msg(us->pusb_dev, usb_rcvctrlpipe(us->pusb_dev,0),						 USB_REQ_GET_STATUS, USB_DIR_IN |						 USB_TYPE_STANDARD | USB_RECIP_DEVICE,						 0, us->ifnum, status, sizeof(status), HZ*5);			if (result != USB_ST_TIMEOUT)				break;		}		if (result) {			US_DEBUGP("Bad AP status request %d\n", result);			return DID_ABORT << 16;		}		US_DEBUGP("Got AP status 0x%x 0x%x\n", status[0], status[1]);		if (srb->cmnd[0] != REQUEST_SENSE && srb->cmnd[0] != INQUIRY &&		    ( (status[0] & ~3) || status[1]))			return (DID_OK << 16) | 2;		else			return USB_STOR_TRANSPORT_GOOD;		break;		/* FIXME: this should be in a separate function */

⌨️ 快捷键说明

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