📄 isd200.c
字号:
if (need_auto_sense) if (isd200_read_regs(us) == ISD200_GOOD) isd200_build_sense(us, srb); /* Regardless of auto-sense, if we _know_ we have an error * condition, show that in the result code */ if (transferStatus == ISD200_TRANSPORT_FAILED) srb->result = CHECK_CONDITION;}/************************************************************************** * 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; US_DEBUGP("Entering isd200_write_config\n"); US_DEBUGP(" Writing the following ISD200 Config Data:\n"); 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.ATAPICommandBlockSize); US_DEBUGP(" Master/Slave Selection: 0x%x\n", info->ConfigData.MasterSlaveSelection); US_DEBUGP(" ATAPI Reset: 0x%x\n", info->ConfigData.ATAPIReset); US_DEBUGP(" ATA Timing: 0x%x\n", info->ConfigData.ATATiming); 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.InitStatus); US_DEBUGP(" Config Descriptor 2: 0x%x\n", info->ConfigData.ConfigDescriptor2); US_DEBUGP(" Skip Device Boot: 0x%x\n", info->ConfigData.SkipDeviceBoot); US_DEBUGP(" ATA 3 State Supsend: 0x%x\n", info->ConfigData.ATA3StateSuspend); US_DEBUGP(" Descriptor Override: 0x%x\n", info->ConfigData.DescriptOverride); US_DEBUGP(" Last LUN Identifier: 0x%x\n", info->ConfigData.LastLUNIdentifier); US_DEBUGP(" SRST Enable: 0x%x\n", info->ConfigData.SRSTEnable); /* 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->pusb_dev, 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"); 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.ATAPICommandBlockSize); US_DEBUGP(" Master/Slave Selection: 0x%x\n", info->ConfigData.MasterSlaveSelection); US_DEBUGP(" ATAPI Reset: 0x%x\n", info->ConfigData.ATAPIReset); US_DEBUGP(" ATA Timing: 0x%x\n", info->ConfigData.ATATiming); 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.InitStatus); US_DEBUGP(" Config Descriptor 2: 0x%x\n", info->ConfigData.ConfigDescriptor2); US_DEBUGP(" Skip Device Boot: 0x%x\n", info->ConfigData.SkipDeviceBoot); US_DEBUGP(" ATA 3 State Supsend: 0x%x\n", info->ConfigData.ATA3StateSuspend); US_DEBUGP(" Descriptor Override: 0x%x\n", info->ConfigData.DescriptOverride); US_DEBUGP(" Last LUN Identifier: 0x%x\n", info->ConfigData.LastLUNIdentifier); US_DEBUGP(" SRST Enable: 0x%x\n", info->ConfigData.SRSTEnable); } 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->pusb_dev, 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"); } /* check for timeout on this request */ if (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.MasterSlaveSelection != isslave) { US_DEBUGP(" Setting Master/Slave selection to %d\n", isslave); info->ConfigData.MasterSlaveSelection = isslave; 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; 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 * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us * in Linux. */ info->InquiryData.Versions = 0x2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -