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

📄 usb_storage.c

📁 F:worksip2440a board可启动u-boot-like.tar.gz F:worksip2440a board可启动u-boot-like.tar.gz
💻 C
📖 第 1 页 / 共 3 页
字号:
{	unsigned char cmd[12];	int result;	USB_STOR_PRINTF("CB_reset\n");	memset(cmd, 0xFF, sizeof(cmd));	cmd[0] = SCSI_SEND_DIAG;	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), USB_CNTL_TIMEOUT*5);	/* long wait for reset */	wait_ms(1500);	USB_STOR_PRINTF("CB_reset result %d: status %X clearing endpoint halt\n",result,us->pusb_dev->status);	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));	USB_STOR_PRINTF("CB_reset done\n");	return 0;}/* * Set up the command for a BBB device. Note that the actual SCSI * command is copied into cbw.CBWCDB. */int usb_stor_BBB_comdat(ccb *srb, struct us_data *us){	int result;	int actlen;	int dir_in;	unsigned int pipe;	umass_bbb_cbw_t cbw;	dir_in = US_DIRECTION(srb->cmd[0]);#ifdef BBB_COMDAT_TRACE	printf("dir %d lun %d cmdlen %d cmd %p datalen %d pdata %p\n", dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen, srb->pdata);	if (srb->cmdlen) {		for(result = 0;result < srb->cmdlen;result++)			printf("cmd[%d] %#x ", result, srb->cmd[result]);		printf("\n");	}#endif	/* sanity checks */	if (!(srb->cmdlen <= CBWCDBLENGTH)) {		USB_STOR_PRINTF("usb_stor_BBB_comdat:cmdlen too large\n");		return -1;	}	/* always OUT to the ep */	pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);	cbw.dCBWSignature = swap_32(CBWSIGNATURE);	cbw.dCBWTag = swap_32(CBWTag++);	cbw.dCBWDataTransferLength = swap_32(srb->datalen);	cbw.bCBWFlags = (dir_in? CBWFLAGS_IN : CBWFLAGS_OUT);	cbw.bCBWLUN = srb->lun;	cbw.bCDBLength = srb->cmdlen;	/* copy the command data into the CBW command data buffer */	/* DST SRC LEN!!! */	memcpy(cbw.CBWCDB, srb->cmd, srb->cmdlen);	result = usb_bulk_msg(us->pusb_dev, pipe, &cbw, UMASS_BBB_CBW_SIZE, &actlen, USB_CNTL_TIMEOUT*5);	if (result < 0)		USB_STOR_PRINTF("usb_stor_BBB_comdat:usb_bulk_msg error\n");	return result;}/* FIXME: we also need a CBI_command which sets up the completion * interrupt, and waits for it */int usb_stor_CB_comdat(ccb *srb, struct us_data *us){	int result;	int dir_in,retry;	unsigned int pipe;	unsigned long status;	retry=5;		dir_in=US_DIRECTION(srb->cmd[0]);		if(dir_in)			pipe=usb_rcvbulkpipe(us->pusb_dev, us->ep_in);		else			pipe=usb_sndbulkpipe(us->pusb_dev, us->ep_out);	while(retry--) {		USB_STOR_PRINTF("CBI gets a command: Try %d\n",5-retry);#ifdef USB_STOR_DEBUG		usb_show_srb(srb);#endif		/* 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->cmd, srb->cmdlen, USB_CNTL_TIMEOUT*5);		USB_STOR_PRINTF("CB_transport: control msg returned %d, status %X\n",result,us->pusb_dev->status);		/* check the return code for the command */		if (result < 0) {			if(us->pusb_dev->status & USB_ST_STALLED) {				status=us->pusb_dev->status;				USB_STOR_PRINTF(" stall during command found, clear pipe\n");				usb_clear_halt(us->pusb_dev,  usb_sndctrlpipe(us->pusb_dev,0));				us->pusb_dev->status=status;			}			USB_STOR_PRINTF(" error during command %02X Stat = %X\n",srb->cmd[0],us->pusb_dev->status);			return result;		}		/* transfer the data payload for this command, if one exists*/		USB_STOR_PRINTF("CB_transport: control msg returned %d, direction is %s to go 0x%lx\n",result,dir_in ? "IN" : "OUT",srb->datalen);		if (srb->datalen) {			result = us_one_transfer(us, pipe, srb->pdata,srb->datalen);			USB_STOR_PRINTF("CBI attempted to transfer data, result is %d status %lX, len %d\n", result,us->pusb_dev->status,us->pusb_dev->act_len);			if(!(us->pusb_dev->status & USB_ST_NAK_REC))				break;		} /* if (srb->datalen) */		else			break;	}	/* return result */	return result;}int usb_stor_CBI_get_status (ccb * srb, struct us_data *us){	int timeout;	us->ip_wanted = 1;	submit_int_msg (us->pusb_dev, us->irqpipe,			(void *) &us->ip_data, us->irqmaxp, us->irqinterval);	timeout = 1000;	while (timeout--) {		if ((volatile int *) us->ip_wanted == 0)			break;		wait_ms (10);	}	if (us->ip_wanted) {		printf ("	Did not get interrupt on CBI\n");		us->ip_wanted = 0;		return USB_STOR_TRANSPORT_ERROR;	}	USB_STOR_PRINTF		("Got interrupt data 0x%x, transfered %d status 0x%lX\n",		 us->ip_data, us->pusb_dev->irq_act_len,		 us->pusb_dev->irq_status);	/* UFI gives us ASC and ASCQ, like a request sense */	if (us->subclass == US_SC_UFI) {		if (srb->cmd[0] == SCSI_REQ_SENSE ||		    srb->cmd[0] == SCSI_INQUIRY)			return USB_STOR_TRANSPORT_GOOD; /* 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;	}			/* switch */	return USB_STOR_TRANSPORT_ERROR;}#define USB_TRANSPORT_UNKNOWN_RETRY 5#define USB_TRANSPORT_NOT_READY_RETRY 10/* clear a stall on an endpoint - special for BBB devices */int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt){	int result;	/* ENDPOINT_HALT = 0, so set value to 0 */	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),				USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,				0, endpt, 0, 0, USB_CNTL_TIMEOUT*5);	return result;}int usb_stor_BBB_transport(ccb *srb, struct us_data *us){	int result, retry;	int dir_in;	int actlen, data_actlen;	unsigned int pipe, pipein, pipeout;	umass_bbb_csw_t csw;#ifdef BBB_XPORT_TRACE	unsigned char *ptr;	int index;#endif	dir_in = US_DIRECTION(srb->cmd[0]);	/* COMMAND phase */	USB_STOR_PRINTF("COMMAND phase\n");	result = usb_stor_BBB_comdat(srb, us);	if (result < 0) {		USB_STOR_PRINTF("failed to send CBW status %ld\n",			us->pusb_dev->status);		usb_stor_BBB_reset(us);		return USB_STOR_TRANSPORT_FAILED;	}	wait_ms(5);	pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);	pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);	/* DATA phase + error handling */	data_actlen = 0;	/* no data, go immediately to the STATUS phase */	if (srb->datalen == 0)		goto st;	USB_STOR_PRINTF("DATA phase\n");	if (dir_in)		pipe = pipein;	else		pipe = pipeout;	result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen, &data_actlen, USB_CNTL_TIMEOUT*5);	/* special handling of STALL in DATA phase */	if((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {		USB_STOR_PRINTF("DATA:stall\n");		/* clear the STALL on the endpoint */		result = usb_stor_BBB_clear_endpt_stall(us, dir_in? us->ep_in : us->ep_out);		if (result >= 0)			/* continue on to STATUS phase */			goto st;	}	if (result < 0) {		USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",			us->pusb_dev->status);		usb_stor_BBB_reset(us);		return USB_STOR_TRANSPORT_FAILED;	}#ifdef BBB_XPORT_TRACE	for (index = 0; index < data_actlen; index++)		printf("pdata[%d] %#x ", index, srb->pdata[index]);	printf("\n");#endif	/* STATUS phase + error handling */   st:	retry = 0;   again:	USB_STOR_PRINTF("STATUS phase\n");	result = usb_bulk_msg(us->pusb_dev, pipein, &csw, UMASS_BBB_CSW_SIZE, &actlen, USB_CNTL_TIMEOUT*5);	/* special handling of STALL in STATUS phase */	if((result < 0) && (retry < 1) && (us->pusb_dev->status & USB_ST_STALLED)) {		USB_STOR_PRINTF("STATUS:stall\n");		/* clear the STALL on the endpoint */		result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);		if (result >= 0 && (retry++ < 1))			/* do a retry */			goto again;	}	if (result < 0) {		USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",			us->pusb_dev->status);		usb_stor_BBB_reset(us);		return USB_STOR_TRANSPORT_FAILED;	}#ifdef BBB_XPORT_TRACE	ptr = (unsigned char *)&csw;	for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)		printf("ptr[%d] %#x ", index, ptr[index]);	printf("\n");#endif	/* misuse pipe to get the residue */	pipe = swap_32(csw.dCSWDataResidue);	if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)		pipe = srb->datalen - data_actlen;	if (CSWSIGNATURE != swap_32(csw.dCSWSignature)) {		USB_STOR_PRINTF("!CSWSIGNATURE\n");		usb_stor_BBB_reset(us);		return USB_STOR_TRANSPORT_FAILED;	} else if ((CBWTag - 1) != swap_32(csw.dCSWTag)) {		USB_STOR_PRINTF("!Tag\n");		usb_stor_BBB_reset(us);		return USB_STOR_TRANSPORT_FAILED;	} else if (csw.bCSWStatus > CSWSTATUS_PHASE) {		USB_STOR_PRINTF(">PHASE\n");		usb_stor_BBB_reset(us);		return USB_STOR_TRANSPORT_FAILED;	} else if (csw.bCSWStatus == CSWSTATUS_PHASE) {		USB_STOR_PRINTF("=PHASE\n");		usb_stor_BBB_reset(us);		return USB_STOR_TRANSPORT_FAILED;	} else if (data_actlen > srb->datalen) {		USB_STOR_PRINTF("transferred %dB instead of %dB\n",			data_actlen, srb->datalen);		return USB_STOR_TRANSPORT_FAILED;	} else if (csw.bCSWStatus == CSWSTATUS_FAILED) {		USB_STOR_PRINTF("FAILED\n");		return USB_STOR_TRANSPORT_FAILED;	}	return result;}int usb_stor_CB_transport(ccb *srb, struct us_data *us){	int result,status;	ccb *psrb;	ccb reqsrb;	int retry,notready;	psrb=&reqsrb;	status=USB_STOR_TRANSPORT_GOOD;	retry=0;	notready=0;	/* issue the command */do_retry:	result=usb_stor_CB_comdat(srb,us);	USB_STOR_PRINTF("command / Data returned %d, status %X\n",result,us->pusb_dev->status);	/* if this is an CBI Protocol, get IRQ */	if(us->protocol==US_PR_CBI) {		status=usb_stor_CBI_get_status(srb,us);		/* if the status is error, report it */		if(status==USB_STOR_TRANSPORT_ERROR) {			USB_STOR_PRINTF(" USB CBI Command Error\n");			return status;		}		srb->sense_buf[12]=(unsigned char)(us->ip_data>>8);		srb->sense_buf[13]=(unsigned char)(us->ip_data&0xff);		if(!us->ip_data) {		/* if the status is good, report it */			if(status==USB_STOR_TRANSPORT_GOOD) {				USB_STOR_PRINTF(" USB CBI Command Good\n");				return status;			}		}	}	/* do we have to issue an auto request? */	/* HERE we have to check the result */	if((result<0) && !(us->pusb_dev->status & USB_ST_STALLED)) {		USB_STOR_PRINTF("ERROR %X\n",us->pusb_dev->status);		us->transport_reset(us);		return USB_STOR_TRANSPORT_ERROR;	}	if((us->protocol==US_PR_CBI) &&			((srb->cmd[0]==SCSI_REQ_SENSE) ||			(srb->cmd[0]==SCSI_INQUIRY))) { /* do not issue an autorequest after request sense */		USB_STOR_PRINTF("No auto request and good\n");		return USB_STOR_TRANSPORT_GOOD;	}	/* issue an request_sense */	memset(&psrb->cmd[0],0,12);	psrb->cmd[0]=SCSI_REQ_SENSE;	psrb->cmd[1]=srb->lun<<5;	psrb->cmd[4]=18;	psrb->datalen=18;	psrb->pdata=&srb->sense_buf[0];	psrb->cmdlen=12;	/* issue the command */	result=usb_stor_CB_comdat(psrb,us);	USB_STOR_PRINTF("auto request returned %d\n",result);	/* if this is an CBI Protocol, get IRQ */	if(us->protocol==US_PR_CBI) {		status=usb_stor_CBI_get_status(psrb,us);	}	if((result<0)&&!(us->pusb_dev->status & USB_ST_STALLED)) {		USB_STOR_PRINTF(" AUTO REQUEST ERROR %d\n",us->pusb_dev->status);		return USB_STOR_TRANSPORT_ERROR;	}	USB_STOR_PRINTF("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",srb->sense_buf[0],srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]);	/* Check the auto request result */	if((srb->sense_buf[2]==0) &&		 (srb->sense_buf[12]==0) &&		 (srb->sense_buf[13]==0)) /* ok, no sense */		return USB_STOR_TRANSPORT_GOOD;	/* Check the auto request result */	switch(srb->sense_buf[2]) {	case 0x01: /* Recovered Error */		return USB_STOR_TRANSPORT_GOOD;		break;	case 0x02: /* Not Ready */		if(notready++ > USB_TRANSPORT_NOT_READY_RETRY) {			printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X 0x%02X (NOT READY)\n",				srb->cmd[0],srb->sense_buf[0],srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]);			return USB_STOR_TRANSPORT_FAILED;		} else {			wait_ms(100);			goto do_retry;		}		break;	default:		if(retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {			printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X 0x%02X\n",				srb->cmd[0],srb->sense_buf[0],srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]);			return USB_STOR_TRANSPORT_FAILED;		} else {			goto do_retry;		}		break;	}

⌨️ 快捷键说明

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