📄 isd200.c
字号:
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 = 0; 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(1) {#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) { US_DEBUGP(" Identified ATAPI device as slave. Rechecking again as master\n"); recheckAsMaster = 1; 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, 0); if (retStatus == ISD200_GOOD) retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_SLAVE, 0); if (retStatus == ISD200_GOOD) { retStatus = isd200_srst(us); if (retStatus == ISD200_GOOD) /* ata or atapi? */ retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, 1); } 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);}/* * We are the last non IDE user of the legacy IDE ident structures * and we thus want to keep a private copy of this function so the * driver can be used without the obsolete drivers/ide layer */static void isd200_fix_driveid (struct hd_driveid *id){#ifndef __LITTLE_ENDIAN# ifdef __BIG_ENDIAN int i; u16 *stringcast; id->config = __le16_to_cpu(id->config); id->cyls = __le16_to_cpu(id->cyls); id->reserved2 = __le16_to_cpu(id->reserved2); id->heads = __le16_to_cpu(id->heads); id->track_bytes = __le16_to_cpu(id->track_bytes); id->sector_bytes = __le16_to_cpu(id->sector_bytes); id->sectors = __le16_to_cpu(id->sectors); id->vendor0 = __le16_to_cpu(id->vendor0); id->vendor1 = __le16_to_cpu(id->vendor1); id->vendor2 = __le16_to_cpu(id->vendor2); stringcast = (u16 *)&id->serial_no[0]; for (i = 0; i < (20/2); i++) stringcast[i] = __le16_to_cpu(stringcast[i]); id->buf_type = __le16_to_cpu(id->buf_type); id->buf_size = __le16_to_cpu(id->buf_size); id->ecc_bytes = __le16_to_cpu(id->ecc_bytes); stringcast = (u16 *)&id->fw_rev[0]; for (i = 0; i < (8/2); i++) stringcast[i] = __le16_to_cpu(stringcast[i]); stringcast = (u16 *)&id->model[0]; for (i = 0; i < (40/2); i++) stringcast[i] = __le16_to_cpu(stringcast[i]); id->dword_io = __le16_to_cpu(id->dword_io); id->reserved50 = __le16_to_cpu(id->reserved50); id->field_valid = __le16_to_cpu(id->field_valid); id->cur_cyls = __le16_to_cpu(id->cur_cyls); id->cur_heads = __le16_to_cpu(id->cur_heads); id->cur_sectors = __le16_to_cpu(id->cur_sectors); id->cur_capacity0 = __le16_to_cpu(id->cur_capacity0); id->cur_capacity1 = __le16_to_cpu(id->cur_capacity1); id->lba_capacity = __le32_to_cpu(id->lba_capacity); id->dma_1word = __le16_to_cpu(id->dma_1word); id->dma_mword = __le16_to_cpu(id->dma_mword); id->eide_pio_modes = __le16_to_cpu(id->eide_pio_modes); id->eide_dma_min = __le16_to_cpu(id->eide_dma_min); id->eide_dma_time = __le16_to_cpu(id->eide_dma_time); id->eide_pio = __le16_to_cpu(id->eide_pio); id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy); for (i = 0; i < 2; ++i) id->words69_70[i] = __le16_to_cpu(id->words69_70[i]); for (i = 0; i < 4; ++i) id->words71_74[i] = __le16_to_cpu(id->words71_74[i]); id->queue_depth = __le16_to_cpu(id->queue_depth); for (i = 0; i < 4; ++i) id->words76_79[i] = __le16_to_cpu(id->words76_79[i]); id->major_rev_num = __le16_to_cpu(id->major_rev_num); id->minor_rev_num = __le16_to_cpu(id->minor_rev_num); id->command_set_1 = __le16_to_cpu(id->command_set_1); id->command_set_2 = __le16_to_cpu(id->command_set_2); id->cfsse = __le16_to_cpu(id->cfsse); id->cfs_enable_1 = __le16_to_cpu(id->cfs_enable_1); id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2); id->csf_default = __le16_to_cpu(id->csf_default); id->dma_ultra = __le16_to_cpu(id->dma_ultra); id->trseuc = __le16_to_cpu(id->trseuc); id->trsEuc = __le16_to_cpu(id->trsEuc); id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues); id->mprc = __le16_to_cpu(id->mprc); id->hw_config = __le16_to_cpu(id->hw_config); id->acoustic = __le16_to_cpu(id->acoustic); id->msrqs = __le16_to_cpu(id->msrqs); id->sxfert = __le16_to_cpu(id->sxfert); id->sal = __le16_to_cpu(id->sal); id->spg = __le32_to_cpu(id->spg); id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2); for (i = 0; i < 22; i++) id->words104_125[i] = __le16_to_cpu(id->words104_125[i]); id->last_lun = __le16_to_cpu(id->last_lun); id->word127 = __le16_to_cpu(id->word127); id->dlf = __le16_to_cpu(id->dlf); id->csfo = __le16_to_cpu(id->csfo); for (i = 0; i < 26; i++) id->words130_155[i] = __le16_to_cpu(id->words130_155[i]); id->word156 = __le16_to_cpu(id->word156); for (i = 0; i < 3; i++) id->words157_159[i] = __le16_to_cpu(id->words157_159[i]); id->cfa_power = __le16_to_cpu(id->cfa_power); for (i = 0; i < 14; i++) id->words161_175[i] = __le16_to_cpu(id->words161_175[i]); for (i = 0; i < 31; i++) id->words176_205[i] = __le16_to_cpu(id->words176_205[i]); for (i = 0; i < 48; i++) id->words206_254[i] = __le16_to_cpu(id->words206_254[i]); id->integrity_word = __le16_to_cpu(id->integrity_word);# else# error "Please fix <asm/byteorder.h>"# endif#endif}/************************************************************************** * isd200_get_inquiry_data * * Get inquiry data * * RETURNS: * ISD status code */static int isd200_get_inquiry_data( struct us_data *us ){ struct isd200_info *info = (struct isd200_info *)us->extra; int retStatus = ISD200_GOOD; struct hd_driveid *id = info->id; 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 Command Identify */ transferStatus = isd200_action( us, ACTION_IDENTIFY, id, 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; __be16 *src; __u16 *dest; isd200_fix_driveid(id); US_DEBUGP(" Identify Data Structure:\n"); US_DEBUGP(" config = 0x%x\n", id->config); US_DEBUGP(" cyls = 0x%x\n", id->cyls); US_DEBUGP(" heads = 0x%x\n", id->heads); US_DEBUGP(" track_bytes = 0x%x\n", id->track_bytes); US_DEBUGP(" sector_bytes = 0x%x\n", id->sector_bytes); US_DEBUGP(" sectors = 0x%x\n", id->sectors); US_DEBUGP(" serial_no[0] = 0x%x\n", id->serial_no[0]); US_DEBUGP(" buf_type = 0x%x\n", id->buf_type); US_DEBUGP(" buf_size = 0x%x\n", id->buf_size); US_DEBUGP(" ecc_bytes = 0x%x\n", id->ecc_bytes); US_DEBUGP(" fw_rev[0] = 0x%x\n", id->fw_rev[0]); US_DEBUGP(" model[0] = 0x%x\n", id->model[0]); US_DEBUGP(" max_multsect = 0x%x\n", id->max_multsect); US_DEBUGP(" dword_io = 0x%x\n", id->dword_io); US_DEBUGP(" capability = 0x%x\n", id->capability); US_DEBUGP(" tPIO = 0x%x\n", id->tPIO); US_DEBUGP(" tDMA = 0x%x\n", id->tDMA); US_DEBUGP(" field_valid = 0x%x\n", id->field_valid); US_DEBUGP(" cur_cyls = 0x%x\n", id->cur_cyls); US_DEBUGP(" cur_heads = 0x%x\n", id->cur_heads); US_DEBUGP(" cur_sectors = 0x%x\n", id->cur_sectors); US_DEBUGP(" cur_capacity = 0x%x\n", (id->cur_capacity1 << 16) + id->cur_capacity0 ); US_DEBUGP(" multsect = 0x%x\n", id->multsect); US_DEBUGP(" lba_capacity = 0x%x\n", id->lba_capacity); US_DEBUGP(" command_set_1 = 0x%x\n", id->command_set_1); US_DEBUGP(" command_set_2 = 0x%x\n", id->command_set_2); memset(&info->InquiryData, 0, sizeof(info->InquiryData)); /* Standard IDE interface only supports disks */ info->InquiryData.DeviceType = DIRECT_ACCESS_DEVICE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -