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

📄 isd200.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		break;	}	memcpy(srb->cmnd, &ata, sizeof(ata.generic));	srb->cmd_len = sizeof(ata.generic);	status = usb_stor_Bulk_transport(srb, us);	if (status == USB_STOR_TRANSPORT_GOOD)		status = ISD200_GOOD;	else {		US_DEBUGP("   isd200_action(0x%02x) error: %d\n",action,status);		status = ISD200_ERROR;		/* need to reset device here */	}	return status;}/************************************************************************** * isd200_read_regs *									  * Read ATA Registers * * RETURNS: *    ISD status code */static int isd200_read_regs( struct us_data *us ){	struct isd200_info *info = (struct isd200_info *)us->extra;	int retStatus = ISD200_GOOD;	int transferStatus;	US_DEBUGP("Entering isd200_IssueATAReadRegs\n");	transferStatus = isd200_action( us, ACTION_READ_STATUS,				    info->RegsBuf, sizeof(info->ATARegs) );	if (transferStatus != ISD200_TRANSPORT_GOOD) {		US_DEBUGP("   Error reading ATA registers\n");		retStatus = ISD200_ERROR;	} else {		memcpy(info->ATARegs, info->RegsBuf, sizeof(info->ATARegs));		US_DEBUGP("   Got ATA Register[IDE_ERROR_OFFSET] = 0x%x\n", 			  info->ATARegs[IDE_ERROR_OFFSET]);	}	return retStatus;}/************************************************************************** * Invoke the transport and basic error-handling/recovery methods * * This is used by the protocol layers to actually send the message to * the device and receive the response. */static void isd200_invoke_transport( struct us_data *us, 			      Scsi_Cmnd *srb, 			      union ata_cdb *ataCdb ){	int need_auto_sense = 0;	int transferStatus;	int result;	/* send the command to the transport layer */	memcpy(srb->cmnd, ataCdb, sizeof(ataCdb->generic));	srb->cmd_len = sizeof(ataCdb->generic);	transferStatus = usb_stor_Bulk_transport(srb, us);	/* if the command gets aborted by the higher layers, we need to	 * short-circuit all other processing	 */	if (us->sm_state == US_STATE_ABORTING) {		US_DEBUGP("-- command was aborted\n");		goto Handle_Abort;	}	switch (transferStatus) {	case USB_STOR_TRANSPORT_GOOD:		/* Indicate a good result */		srb->result = SAM_STAT_GOOD;		break;	case USB_STOR_TRANSPORT_NO_SENSE:		US_DEBUGP("-- transport indicates protocol failure\n");		srb->result = SAM_STAT_CHECK_CONDITION;		return;	case USB_STOR_TRANSPORT_FAILED:		US_DEBUGP("-- transport indicates command failure\n");		need_auto_sense = 1;		break;	case USB_STOR_TRANSPORT_ERROR:		US_DEBUGP("-- transport indicates transport error\n");		srb->result = DID_ERROR << 16;		/* Need reset here */		return;    	default:		US_DEBUGP("-- transport indicates unknown error\n");   		srb->result = DID_ERROR << 16;		/* Need reset here */		return;	}	if ((srb->resid > 0) &&	    !((srb->cmnd[0] == REQUEST_SENSE) ||	      (srb->cmnd[0] == INQUIRY) ||	      (srb->cmnd[0] == MODE_SENSE) ||	      (srb->cmnd[0] == LOG_SENSE) ||	      (srb->cmnd[0] == MODE_SENSE_10))) {		US_DEBUGP("-- unexpectedly short transfer\n");		need_auto_sense = 1;	}	if (need_auto_sense) {		result = isd200_read_regs(us);		if (us->sm_state == US_STATE_ABORTING) {			US_DEBUGP("-- auto-sense aborted\n");			goto Handle_Abort;		}		if (result == ISD200_GOOD) {			isd200_build_sense(us, srb);			srb->result = SAM_STAT_CHECK_CONDITION;			/* If things are really okay, then let's show that */			if ((srb->sense_buffer[2] & 0xf) == 0x0)				srb->result = SAM_STAT_GOOD;		} else {			srb->result = DID_ERROR << 16;			/* Need reset here */		}	}	/* Regardless of auto-sense, if we _know_ we have an error	 * condition, show that in the result code	 */	if (transferStatus == USB_STOR_TRANSPORT_FAILED)		srb->result = SAM_STAT_CHECK_CONDITION;	return;	/* abort processing: the bulk-only transport requires a reset	 * following an abort */	Handle_Abort:	srb->result = DID_ABORT << 16;	/* permit the reset transfer to take place */	clear_bit(US_FLIDX_ABORTING, &us->flags);	/* Need reset here */}#ifdef CONFIG_USB_STORAGE_DEBUGstatic void isd200_log_config( struct isd200_info* info ){	US_DEBUGP("      Event Notification: 0x%x\n", 		  info->ConfigData.EventNotification);	US_DEBUGP("      External Clock: 0x%x\n", 		  info->ConfigData.ExternalClock);	US_DEBUGP("      ATA Init Timeout: 0x%x\n", 		  info->ConfigData.ATAInitTimeout);	US_DEBUGP("      ATAPI Command Block Size: 0x%x\n", 		  (info->ConfigData.ATAConfig & ATACFG_BLOCKSIZE) >> 6);	US_DEBUGP("      Master/Slave Selection: 0x%x\n", 		  info->ConfigData.ATAConfig & ATACFG_MASTER);	US_DEBUGP("      ATAPI Reset: 0x%x\n",		  info->ConfigData.ATAConfig & ATACFG_ATAPI_RESET);	US_DEBUGP("      ATA Timing: 0x%x\n",		  info->ConfigData.ATAConfig & ATACFG_TIMING);	US_DEBUGP("      ATA Major Command: 0x%x\n", 		  info->ConfigData.ATAMajorCommand);	US_DEBUGP("      ATA Minor Command: 0x%x\n", 		  info->ConfigData.ATAMinorCommand);	US_DEBUGP("      Init Status: 0x%x\n", 		  info->ConfigData.ATAExtraConfig & ATACFGE_INIT_STATUS);	US_DEBUGP("      Config Descriptor 2: 0x%x\n", 		  info->ConfigData.ATAExtraConfig & ATACFGE_CONF_DESC2);	US_DEBUGP("      Skip Device Boot: 0x%x\n",		  info->ConfigData.ATAExtraConfig & ATACFGE_SKIP_BOOT);	US_DEBUGP("      ATA 3 State Supsend: 0x%x\n",		  info->ConfigData.ATAExtraConfig & ATACFGE_STATE_SUSPEND);	US_DEBUGP("      Descriptor Override: 0x%x\n", 		  info->ConfigData.ATAExtraConfig & ATACFGE_DESC_OVERRIDE);	US_DEBUGP("      Last LUN Identifier: 0x%x\n",		  info->ConfigData.ATAExtraConfig & ATACFGE_LAST_LUN);	US_DEBUGP("      SRST Enable: 0x%x\n", 		  info->ConfigData.ATAExtraConfig & CFG_CAPABILITY_SRST);}#endif/************************************************************************** * isd200_write_config *									  * Write the ISD200 Configuration data * * RETURNS: *    ISD status code */static int isd200_write_config( struct us_data *us ) {	struct isd200_info *info = (struct isd200_info *)us->extra;	int retStatus = ISD200_GOOD;	int result;#ifdef CONFIG_USB_STORAGE_DEBUG	US_DEBUGP("Entering isd200_write_config\n");	US_DEBUGP("   Writing the following ISD200 Config Data:\n");	isd200_log_config(info);#endif	/* let's send the command via the control pipe */	result = usb_stor_ctrl_transfer(		us, 		us->send_ctrl_pipe,		0x01, 		USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,		0x0000, 		0x0002, 		(void *) &info->ConfigData, 		sizeof(info->ConfigData));	if (result >= 0) {		US_DEBUGP("   ISD200 Config Data was written successfully\n");	} else {		US_DEBUGP("   Request to write ISD200 Config Data failed!\n");		retStatus = ISD200_ERROR;	}	US_DEBUGP("Leaving isd200_write_config %08X\n", retStatus);	return retStatus;}/************************************************************************** * isd200_read_config *									  * Reads the ISD200 Configuration data * * RETURNS: *    ISD status code */static int isd200_read_config( struct us_data *us ) {	struct isd200_info *info = (struct isd200_info *)us->extra;	int retStatus = ISD200_GOOD;	int result;	US_DEBUGP("Entering isd200_read_config\n");	/* read the configuration information from ISD200.  Use this to */	/* determine what the special ATA CDB bytes are.		*/	result = usb_stor_ctrl_transfer(		us, 		us->recv_ctrl_pipe,		0x02, 		USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,		0x0000, 		0x0002, 		(void *) &info->ConfigData, 		sizeof(info->ConfigData));	if (result >= 0) {		US_DEBUGP("   Retrieved the following ISD200 Config Data:\n");#ifdef CONFIG_USB_STORAGE_DEBUG		isd200_log_config(info);#endif	} else {		US_DEBUGP("   Request to get ISD200 Config Data failed!\n");		retStatus = ISD200_ERROR;	}	US_DEBUGP("Leaving isd200_read_config %08X\n", retStatus);	return retStatus;}/************************************************************************** * isd200_atapi_soft_reset *									  * Perform an Atapi Soft Reset on the device * * RETURNS: *    NT status code */static int isd200_atapi_soft_reset( struct us_data *us ) {	int retStatus = ISD200_GOOD;	int transferStatus;	US_DEBUGP("Entering isd200_atapi_soft_reset\n");	transferStatus = isd200_action( us, ACTION_SOFT_RESET, NULL, 0 );	if (transferStatus != ISD200_TRANSPORT_GOOD) {		US_DEBUGP("   Error issuing Atapi Soft Reset\n");		retStatus = ISD200_ERROR;	}	US_DEBUGP("Leaving isd200_atapi_soft_reset %08X\n", retStatus);	return retStatus;}/************************************************************************** * isd200_srst *									  * Perform an SRST on the device * * RETURNS: *    ISD status code */static int isd200_srst( struct us_data *us ) {	int retStatus = ISD200_GOOD;	int transferStatus;	US_DEBUGP("Entering isd200_SRST\n");	transferStatus = isd200_action( us, ACTION_RESET, NULL, 0 );	/* check to see if this request failed */	if (transferStatus != ISD200_TRANSPORT_GOOD) {		US_DEBUGP("   Error issuing SRST\n");		retStatus = ISD200_ERROR;	} else {		/* delay 10ms to give the drive a chance to see it */		msleep(10);		transferStatus = isd200_action( us, ACTION_REENABLE, NULL, 0 );		if (transferStatus != ISD200_TRANSPORT_GOOD) {			US_DEBUGP("   Error taking drive out of reset\n");			retStatus = ISD200_ERROR;		} else {			/* delay 50ms to give the drive a chance to recover after SRST */			msleep(50);		}	}	US_DEBUGP("Leaving isd200_srst %08X\n", retStatus);	return retStatus;}/************************************************************************** * isd200_try_enum *									  * Helper function for isd200_manual_enum(). Does ENUM and READ_STATUS * and tries to analyze the status registers * * RETURNS: *    ISD status code */static int isd200_try_enum(struct us_data *us, unsigned char master_slave,			   int detect ){	int status = ISD200_GOOD;	unsigned long endTime;	struct isd200_info *info = (struct isd200_info *)us->extra;	unsigned char *regs = info->RegsBuf;	int recheckAsMaster = FALSE;	if ( detect )		endTime = jiffies + ISD200_ENUM_DETECT_TIMEOUT * HZ;	else		endTime = jiffies + ISD200_ENUM_BSY_TIMEOUT * HZ;	/* loop until we detect !BSY or timeout */	while(TRUE) {#ifdef CONFIG_USB_STORAGE_DEBUG		char* mstr = master_slave == ATA_ADDRESS_DEVHEAD_STD ?			"Master" : "Slave";#endif		status = isd200_action( us, ACTION_ENUM, NULL, master_slave );		if ( status != ISD200_GOOD )			break;		status = isd200_action( us, ACTION_READ_STATUS, 					regs, 8 );		if ( status != ISD200_GOOD )			break;		if (!detect) {			if (regs[IDE_STATUS_OFFSET] & BUSY_STAT ) {				US_DEBUGP("   %s status is still BSY, try again...\n",mstr);			} else {				US_DEBUGP("   %s status !BSY, continue with next operation\n",mstr);				break;			}		}		/* check for BUSY_STAT and */		/* WRERR_STAT (workaround ATA Zip drive) and */ 		/* ERR_STAT (workaround for Archos CD-ROM) */		else if (regs[IDE_STATUS_OFFSET] & 			 (BUSY_STAT | WRERR_STAT | ERR_STAT )) {			US_DEBUGP("   Status indicates it is not ready, try again...\n");		}		/* check for DRDY, ATA devices set DRDY after SRST */		else if (regs[IDE_STATUS_OFFSET] & READY_STAT) {			US_DEBUGP("   Identified ATA device\n");			info->DeviceFlags |= DF_ATA_DEVICE;			info->DeviceHead = master_slave;			break;		} 		/* check Cylinder High/Low to		   determine if it is an ATAPI device		*/		else if ((regs[IDE_HCYL_OFFSET] == 0xEB) &&			 (regs[IDE_LCYL_OFFSET] == 0x14)) {			/* It seems that the RICOH 			   MP6200A CD/RW drive will 			   report itself okay as a			   slave when it is really a			   master. So this check again			   as a master device just to			   make sure it doesn't report			   itself okay as a master also			*/			if ((master_slave & ATA_ADDRESS_DEVHEAD_SLAVE) &&			    (recheckAsMaster == FALSE)) {				US_DEBUGP("   Identified ATAPI device as slave.  Rechecking again as master\n");				recheckAsMaster = TRUE;				master_slave = ATA_ADDRESS_DEVHEAD_STD;			} else {				US_DEBUGP("   Identified ATAPI device\n");				info->DeviceHead = master_slave;			      				status = isd200_atapi_soft_reset(us);				break;			}		} else { 			US_DEBUGP("   Not ATA, not ATAPI. Weird.\n");			break;		}		/* check for timeout on this request */		if (time_after_eq(jiffies, endTime)) {			if (!detect)				US_DEBUGP("   BSY check timeout, just continue with next operation...\n");			else				US_DEBUGP("   Device detect timeout!\n");			break;		}	}	return status;}/************************************************************************** * isd200_manual_enum *									  * Determines if the drive attached is an ATA or ATAPI and if it is a * master or slave. * * RETURNS: *    ISD status code */static int isd200_manual_enum(struct us_data *us){	struct isd200_info *info = (struct isd200_info *)us->extra;	int retStatus = ISD200_GOOD;	US_DEBUGP("Entering isd200_manual_enum\n");	retStatus = isd200_read_config(us);	if (retStatus == ISD200_GOOD) {		int isslave;		/* master or slave? */		retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, FALSE );		if (retStatus == ISD200_GOOD)			retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_SLAVE, FALSE );		if (retStatus == ISD200_GOOD) {			retStatus = isd200_srst(us);			if (retStatus == ISD200_GOOD)				/* ata or atapi? */				retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, TRUE );		}		isslave = (info->DeviceHead & ATA_ADDRESS_DEVHEAD_SLAVE) ? 1 : 0;		if (!(info->ConfigData.ATAConfig & ATACFG_MASTER)) {			US_DEBUGP("   Setting Master/Slave selection to %d\n", isslave);

⌨️ 快捷键说明

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