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

📄 transport.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* re-initialize the mutex so that we avoid any races with	 * early/late IRQs from previous commands */	init_MUTEX_LOCKED(&(us->ip_waitq));	/* COMMAND STAGE */	/* let's send the command via the control pipe */	result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0),				      US_CBI_ADSC, 				      USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, 				      us->ifnum, srb->cmnd, srb->cmd_len);	/* check the return code for the command */	US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result);	if (result < 0) {		/* Reset flag for status notification */		atomic_set(us->ip_wanted, 0);		/* if the command was aborted, indicate that */		if (result == -ENOENT)			return USB_STOR_TRANSPORT_ABORTED;		/* STALL must be cleared when they are detected */		if (result == -EPIPE) {			US_DEBUGP("-- Stall on control pipe. Clearing\n");			result = usb_stor_clear_halt(us->pusb_dev,						    usb_sndctrlpipe(us->pusb_dev,							    0));			US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result);			return USB_STOR_TRANSPORT_FAILED;		}		/* Uh oh... serious problem here */		return USB_STOR_TRANSPORT_ERROR;	}	/* DATA STAGE */	/* transfer the data payload for this command, if one exists*/	if (usb_stor_transfer_length(srb)) {		usb_stor_transfer(srb, us);		US_DEBUGP("CBI data stage result is 0x%x\n", srb->result);		/* if it was aborted, we need to indicate that */		if (srb->result == USB_STOR_TRANSPORT_ABORTED) {			return USB_STOR_TRANSPORT_ABORTED;		}	}	/* STATUS STAGE */	/* go to sleep until we get this interrupt */	US_DEBUGP("Current value of ip_waitq is: %d\n", atomic_read(&us->ip_waitq.count));	down(&(us->ip_waitq));	/* if we were woken up by an abort instead of the actual interrupt */	if (atomic_read(us->ip_wanted)) {		US_DEBUGP("Did not get interrupt on CBI\n");		atomic_set(us->ip_wanted, 0);		return USB_STOR_TRANSPORT_ABORTED;	}	US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", 			us->irqdata[0], us->irqdata[1]);	/* UFI gives us ASC and ASCQ, like a request sense	 *	 * REQUEST_SENSE and INQUIRY don't affect the sense data on UFI	 * devices, so we ignore the information for those commands.  Note	 * that this means we could be ignoring a real error on these	 * commands, but that can't be helped.	 */	if (us->subclass == US_SC_UFI) {		if (srb->cmnd[0] == REQUEST_SENSE ||		    srb->cmnd[0] == INQUIRY)			return USB_STOR_TRANSPORT_GOOD;		else			if (((unsigned char*)us->irq_urb->transfer_buffer)[0])				return USB_STOR_TRANSPORT_FAILED;			else				return USB_STOR_TRANSPORT_GOOD;	}	/* If not UFI, we interpret the data as a result code 	 * The first byte should always be a 0x0	 * The second byte & 0x0F should be 0x0 for good, otherwise error 	 */	if (us->irqdata[0]) {		US_DEBUGP("CBI IRQ data showed reserved bType %d\n",				us->irqdata[0]);		return USB_STOR_TRANSPORT_ERROR;	}	switch (us->irqdata[1] & 0x0F) {		case 0x00: 			return USB_STOR_TRANSPORT_GOOD;		case 0x01: 			return USB_STOR_TRANSPORT_FAILED;		default: 			return USB_STOR_TRANSPORT_ERROR;	}	/* we should never get here, but if we do, we're in trouble */	return USB_STOR_TRANSPORT_ERROR;}/* * Control/Bulk transport */int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us){	int result;	/* COMMAND STAGE */	/* let's send the command via the control pipe */	result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0),				      US_CBI_ADSC, 				      USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, 				      us->ifnum, srb->cmnd, srb->cmd_len);	/* check the return code for the command */	US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result);	if (result < 0) {		/* if the command was aborted, indicate that */		if (result == -ENOENT)			return USB_STOR_TRANSPORT_ABORTED;		/* a stall is a fatal condition from the device */		if (result == -EPIPE) {			US_DEBUGP("-- Stall on control pipe. Clearing\n");			result = usb_stor_clear_halt(us->pusb_dev, 					    usb_sndctrlpipe(us->pusb_dev,							    0));			US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result);			return USB_STOR_TRANSPORT_FAILED;		}		/* Uh oh... serious problem here */		return USB_STOR_TRANSPORT_ERROR;	}	/* DATA STAGE */	/* transfer the data payload for this command, if one exists*/	if (usb_stor_transfer_length(srb)) {		usb_stor_transfer(srb, us);		US_DEBUGP("CB data stage result is 0x%x\n", srb->result);		/* if it was aborted, we need to indicate that */		if (srb->result == USB_STOR_TRANSPORT_ABORTED)			return USB_STOR_TRANSPORT_ABORTED;	}	/* STATUS STAGE */	/* NOTE: CB does not have a status stage.  Silly, I know.  So	 * we have to catch this at a higher level.	 */	return USB_STOR_TRANSPORT_GOOD;}/* * Bulk only transport *//* Determine what the maximum LUN supported is */int usb_stor_Bulk_max_lun(struct us_data *us){	unsigned char data;	int result;	int pipe;	/* issue the command */	pipe = usb_rcvctrlpipe(us->pusb_dev, 0);	result = usb_control_msg(us->pusb_dev, pipe,				 US_BULK_GET_MAX_LUN, 				 USB_DIR_IN | USB_TYPE_CLASS | 				 USB_RECIP_INTERFACE,				 0, us->ifnum, &data, sizeof(data), HZ);	US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", 		  result, data);	/* if we have a successful request, return the result */	if (result == 1)		return data;	/* if we get a STALL, clear the stall */	if (result == -EPIPE) {		US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);		usb_stor_clear_halt(us->pusb_dev, pipe);	}	/* return the default -- no LUNs */	return 0;}int usb_stor_Bulk_reset(struct us_data *us);int usb_stor_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;	/* if the device was removed, then we're already reset */	if (!us->pusb_dev)		return SUCCESS;	/* set up the command wrapper */	bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);	bcb.DataTransferLength = cpu_to_le32(usb_stor_transfer_length(srb));	bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;	bcb.Tag = srb->serial_number;	bcb.Lun = srb->cmnd[1] >> 5;	if (us->flags & US_FL_SCM_MULT_TARG)		bcb.Lun |= srb->target << 4;	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 Trg %d LUN %d L %d F %d CL %d\n",		  le32_to_cpu(bcb.Signature), bcb.Tag,		  (bcb.Lun >> 4), (bcb.Lun & 0x0F), 		  bcb.DataTransferLength, bcb.Flags, bcb.Length);	result = usb_stor_bulk_msg(us, &bcb, pipe, US_BULK_CB_WRAP_LEN, 				   &partial);	US_DEBUGP("Bulk command transfer result=%d\n", result);	/* if the command was aborted, indicate that */	if (result == -ENOENT)		return USB_STOR_TRANSPORT_ABORTED;	/* 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_stor_clear_halt(us->pusb_dev, pipe);	} else if (result) {		/* unknown error -- we've got a problem */		return USB_STOR_TRANSPORT_ERROR;	}	/* if the command transfered well, then we go to the data stage */	if (result == 0) {		/* send/receive data payload, if there is any */		if (bcb.DataTransferLength) {			usb_stor_transfer(srb, us);			US_DEBUGP("Bulk data transfer result 0x%x\n", 				  srb->result);			/* if it was aborted, we need to indicate that */			if (srb->result == USB_STOR_TRANSPORT_ABORTED)				return USB_STOR_TRANSPORT_ABORTED;		}	}	/* 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 */	US_DEBUGP("Attempting to get CSW...\n");	result = usb_stor_bulk_msg(us, &bcs, pipe, US_BULK_CS_WRAP_LEN, 				   &partial);	/* if the command was aborted, indicate that */	if (result == -ENOENT)		return USB_STOR_TRANSPORT_ABORTED;	/* did the attempt to read the CSW fail? */	if (result == -EPIPE) {		US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);		usb_stor_clear_halt(us->pusb_dev, pipe);	       		/* get the status again */		US_DEBUGP("Attempting to get CSW (2nd try)...\n");		result = usb_stor_bulk_msg(us, &bcs, pipe,					   US_BULK_CS_WRAP_LEN, &partial);		/* if the command was aborted, indicate that */		if (result == -ENOENT)			return USB_STOR_TRANSPORT_ABORTED;		/* if it fails again, we need a reset and return an error*/		if (result == -EPIPE) {			US_DEBUGP("clearing halt for pipe 0x%x\n", pipe);			usb_stor_clear_halt(us->pusb_dev, pipe);			return USB_STOR_TRANSPORT_ERROR;		}	}	/* if we still have a failure at this point, we're in trouble */	US_DEBUGP("Bulk status result = %d\n", result);	if (result) {		return USB_STOR_TRANSPORT_ERROR;	}	/* check bulk status */	US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n",		  le32_to_cpu(bcs.Signature), bcs.Tag, 		  bcs.Residue, bcs.Status);	if (bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) ||#if !defined(CONFIG_USB_UHCI124) && !defined(CONFIG_USB_UHCI124_MODULE)		   		    bcs.Tag != bcb.Tag || #else				    ((bcs.Tag != bcb.Tag) && !(us->flags & US_FL_QUIRKS_TAG)) ||#endif			    bcs.Status > US_BULK_STAT_PHASE || partial != 13) {		US_DEBUGP("Bulk logical error\n");		return USB_STOR_TRANSPORT_ERROR;	}	/* based on the status code, we report good or bad */	switch (bcs.Status) {		case US_BULK_STAT_OK:			/* command good -- note that data could be short */			return USB_STOR_TRANSPORT_GOOD;		case US_BULK_STAT_FAIL:			/* command failed */			return USB_STOR_TRANSPORT_FAILED;		case US_BULK_STAT_PHASE:			/* phase error -- note that a transport reset will be			 * invoked by the invoke_transport() function			 */			return USB_STOR_TRANSPORT_ERROR;	}	/* we should never get here, but if we do, we're in trouble */	return USB_STOR_TRANSPORT_ERROR;}/*********************************************************************** * Reset routines ***********************************************************************//* This issues a CB[I] Reset to the device in question */int usb_stor_CB_reset(struct us_data *us){	unsigned char cmd[12];	int result;	US_DEBUGP("CB_reset() called\n");	/* if the device was removed, then we're already reset */	if (!us->pusb_dev)		return SUCCESS;	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);	if (result < 0) {		US_DEBUGP("CB[I] soft reset failed %d\n", result);		return FAILED;	}	/* long wait for reset */	set_current_state(TASK_UNINTERRUPTIBLE);	schedule_timeout(HZ*6);	set_current_state(TASK_RUNNING);	US_DEBUGP("CB_reset: clearing endpoint halt\n");	usb_stor_clear_halt(us->pusb_dev, 			    usb_rcvbulkpipe(us->pusb_dev, us->ep_in));	usb_stor_clear_halt(us->pusb_dev, 			    usb_rcvbulkpipe(us->pusb_dev, us->ep_out));	US_DEBUGP("CB_reset done\n");	/* return a result code based on the result of the control message */	return SUCCESS;}/* This issues a Bulk-only Reset to the device in question, including * clearing the subsequent endpoint halts that may occur. */int usb_stor_Bulk_reset(struct us_data *us){	int result;	US_DEBUGP("Bulk reset requested\n");	/* if the device was removed, then we're already reset */	if (!us->pusb_dev)		return SUCCESS;	result = usb_control_msg(us->pusb_dev, 				 usb_sndctrlpipe(us->pusb_dev,0), 				 US_BULK_RESET_REQUEST, 				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,				 0, us->ifnum, NULL, 0, HZ*5);	if (result < 0) {		US_DEBUGP("Bulk soft reset failed %d\n", result);		return FAILED;	}	/* long wait for reset */	set_current_state(TASK_UNINTERRUPTIBLE);	schedule_timeout(HZ*6);	set_current_state(TASK_RUNNING);	usb_stor_clear_halt(us->pusb_dev, 			    usb_rcvbulkpipe(us->pusb_dev, us->ep_in));	usb_stor_clear_halt(us->pusb_dev, 			    usb_sndbulkpipe(us->pusb_dev, us->ep_out));	US_DEBUGP("Bulk soft reset completed\n");	return SUCCESS;}

⌨️ 快捷键说明

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