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

📄 isd200.c

📁 LINUX下USB驱动程序的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
{	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 Configuraton data * * RETURNS: *    ISD status code */                                                                        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_control_msg(                us,                 usb_sndctrlpipe(us->pusb_dev,0),                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");		/* 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,					usb_sndctrlpipe(us->pusb_dev, 0));			US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result);		}		retStatus = ISD200_ERROR;        }	US_DEBUGP("Leaving isd200_write_config %08X\n", retStatus);	return retStatus;}/************************************************************************** * isd200_read_config *                                                                          * Reads the ISD200 Configuraton data * * RETURNS: *    ISD status code */                                                                        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_control_msg(                us,                 usb_rcvctrlpipe(us->pusb_dev,0),                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");		/* 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,   					usb_sndctrlpipe(us->pusb_dev, 0));			US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result);		}		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 */                                                                        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 */                                                                        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 */		wait_ms(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 */			wait_ms(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 char regs[8];	unsigned long endTime;	struct isd200_info *info = (struct isd200_info *)us->extra;	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, sizeof(regs) );		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 */                                                                        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);			info->ConfigData.ATAConfig &= 0x3f;			info->ConfigData.ATAConfig |= (isslave<<6);			retStatus = isd200_write_config(us);		}	}	US_DEBUGP("Leaving isd200_manual_enum %08X\n", retStatus);	return(retStatus);}/************************************************************************** * isd200_get_inquiry_data * * Get inquiry data * * RETURNS: *    ISD status code */int isd200_get_inquiry_data( struct us_data *us ){	struct isd200_info *info = (struct isd200_info *)us->extra;	int retStatus = ISD200_GOOD;	US_DEBUGP("Entering isd200_get_inquiry_data\n");	/* set default to Master */	info->DeviceHead = ATA_ADDRESS_DEVHEAD_STD;	/* attempt to manually enumerate this device */	retStatus = isd200_manual_enum(us);	if (retStatus == ISD200_GOOD) {		int transferStatus;		/* check for an ATA device */		if (info->DeviceFlags & DF_ATA_DEVICE) {			/* this must be an ATA device */			/* perform an ATA Commmand Identify */			transferStatus = isd200_action( us, ACTION_IDENTIFY,							&info->drive, 							sizeof(struct hd_driveid) );			if (transferStatus != ISD200_TRANSPORT_GOOD) {				/* Error issuing ATA Command Identify */				US_DEBUGP("   Error issuing ATA Command Identify\n");				retStatus = ISD200_ERROR;			} else {				/* ATA Command Identify successful */				int i;				__u16 *src, *dest;				ide_fix_driveid(&info->drive);				US_DEBUGP("   Identify Data Structure:\n");				US_DEBUGP("      config = 0x%x\n", info->drive.config);				US_DEBUGP("      cyls = 0x%x\n", info->drive.cyls);				US_DEBUGP("      heads = 0x%x\n", info->drive.heads);				US_DEBUGP("      track_bytes = 0x%x\n", info->drive.track_bytes);				US_DEBUGP("      sector_bytes = 0x%x\n", info->drive.sector_bytes);				US_DEBUGP("      sectors = 0x%x\n", info->drive.sectors);				US_DEBUGP("      serial_no[0] = 0x%x\n", info->drive.serial_no[0]);				US_DEBUGP("      buf_type = 0x%x\n", info->drive.buf_type);				US_DEBUGP("      buf_size = 0x%x\n", info->drive.buf_size);				US_DEBUGP("      ecc_bytes = 0x%x\n", info->drive.ecc_bytes);				US_DEBUGP("      fw_rev[0] = 0x%x\n", info->drive.fw_rev[0]);				US_DEBUGP("      model[0] = 0x%x\n", info->drive.model[0]);				US_DEBUGP("      max_multsect = 0x%x\n", info->drive.max_multsect);				US_DEBUGP("      dword_io = 0x%x\n", info->drive.dword_io);				US_DEBUGP("      capability = 0x%x\n", info->drive.capability);				US_DEBUGP("      tPIO = 0x%x\n", info->drive.tPIO);				US_DEBUGP("      tDMA = 0x%x\n", info->drive.tDMA);				US_DEBUGP("      field_valid = 0x%x\n", info->drive.field_valid);				US_DEBUGP("      cur_cyls = 0x%x\n", info->drive.cur_cyls);				US_DEBUGP("      cur_heads = 0x%x\n", info->drive.cur_heads);				US_DEBUGP("      cur_sectors = 0x%x\n", info->drive.cur_sectors);				US_DEBUGP("      cur_capacity = 0x%x\n", (info->drive.cur_capacity1 << 16) + info->drive.cur_capacity0 );				US_DEBUGP("      multsect = 0x%x\n", info->drive.multsect);				US_DEBUGP("      lba_capacity = 0x%x\n", info->drive.lba_capacity);				US_DEBUGP("      command_set_1 = 0x%x\n", info->drive.command_set_1);				US_DEBUGP("      command_set_2 = 0x%x\n", info->drive.command_set_2);				memset(&info->InquiryData, 0, sizeof(info->InquiryData));				/* Standard IDE interface only supports disks */				info->InquiryData.DeviceType = DIRECT_ACCESS_DEVICE;				/* Fix-up the return data from an INQUIRY command to show 

⌨️ 快捷键说明

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