📄 isd200.c
字号:
} else { buf->ErrorCode = 0; buf->AdditionalSenseLength = 0; buf->Flags = 0; buf->AdditionalSenseCode = 0; buf->AdditionalSenseCodeQualifier = 0; }}/*********************************************************************** * Transport routines ***********************************************************************//************************************************************************** * isd200_action * * Routine for sending commands to the isd200 * * RETURNS: * ISD status code */static int isd200_action( struct us_data *us, int action, void* pointer, int value ){ union ata_cdb ata; struct scsi_device srb_dev; struct isd200_info *info = (struct isd200_info *)us->extra; struct scsi_cmnd *srb = &info->srb; int status; memset(&ata, 0, sizeof(ata)); memset(&srb_dev, 0, sizeof(srb_dev)); srb->device = &srb_dev; ++srb->serial_number; ata.generic.SignatureByte0 = info->ConfigData.ATAMajorCommand; ata.generic.SignatureByte1 = info->ConfigData.ATAMinorCommand; ata.generic.TransferBlockSize = 1; switch ( action ) { case ACTION_READ_STATUS: US_DEBUGP(" isd200_action(READ_STATUS)\n"); ata.generic.ActionSelect = ACTION_SELECT_0|ACTION_SELECT_2; ata.generic.RegisterSelect = REG_CYLINDER_LOW | REG_CYLINDER_HIGH | REG_STATUS | REG_ERROR; srb->sc_data_direction = DMA_FROM_DEVICE; srb->request_buffer = pointer; srb->request_bufflen = value; break; case ACTION_ENUM: US_DEBUGP(" isd200_action(ENUM,0x%02x)\n",value); ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2| ACTION_SELECT_3|ACTION_SELECT_4| ACTION_SELECT_5; ata.generic.RegisterSelect = REG_DEVICE_HEAD; ata.write.DeviceHeadByte = value; srb->sc_data_direction = DMA_NONE; break; case ACTION_RESET: US_DEBUGP(" isd200_action(RESET)\n"); ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2| ACTION_SELECT_3|ACTION_SELECT_4; ata.generic.RegisterSelect = REG_DEVICE_CONTROL; ata.write.DeviceControlByte = ATA_DC_RESET_CONTROLLER; srb->sc_data_direction = DMA_NONE; break; case ACTION_REENABLE: US_DEBUGP(" isd200_action(REENABLE)\n"); ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2| ACTION_SELECT_3|ACTION_SELECT_4; ata.generic.RegisterSelect = REG_DEVICE_CONTROL; ata.write.DeviceControlByte = ATA_DC_REENABLE_CONTROLLER; srb->sc_data_direction = DMA_NONE; break; case ACTION_SOFT_RESET: US_DEBUGP(" isd200_action(SOFT_RESET)\n"); ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_5; ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND; ata.write.DeviceHeadByte = info->DeviceHead; ata.write.CommandByte = WIN_SRST; srb->sc_data_direction = DMA_NONE; break; case ACTION_IDENTIFY: US_DEBUGP(" isd200_action(IDENTIFY)\n"); ata.generic.RegisterSelect = REG_COMMAND; ata.write.CommandByte = WIN_IDENTIFY; srb->sc_data_direction = DMA_FROM_DEVICE; srb->request_buffer = (void *) info->id; srb->request_bufflen = sizeof(struct hd_driveid); break; default: US_DEBUGP("Error: Undefined action %d\n",action); 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, struct 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 (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { 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 (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -