📄 isd200.c
字号:
/* Transport & Protocol Driver for In-System Design, Inc. ISD200 ASIC * * First release * * Current development and maintenance by: * (c) 2000 In-System Design, Inc. (support@in-system.com) * * The ISD200 ASIC does not natively support ATA devices. The chip * does implement an interface, the ATA Command Block (ATACB) which provides * a means of passing ATA commands and ATA register accesses to a device. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. * * History: * * 2001-02-24: Removed lots of duplicate code and simplified the structure. * (bjorn@haxx.se) *//* Include files */#include "transport.h"#include "protocol.h"#include "usb.h"#include "debug.h"#include "scsiglue.h"#include "isd200.h"#include <linux/sched.h>#include <linux/errno.h>#include <linux/slab.h>#include <linux/hdreg.h>#include <linux/ide.h>/* * Inquiry defines. Used to interpret data returned from target as result * of inquiry command. * * DeviceType field */#define DIRECT_ACCESS_DEVICE 0x00 /* disks *//* Timeout defines (in Seconds) */#define ISD200_ENUM_BSY_TIMEOUT 35#define ISD200_ENUM_DETECT_TIMEOUT 30#define ISD200_DEFAULT_TIMEOUT 30/* device flags */#define DF_ATA_DEVICE 0x0001#define DF_MEDIA_STATUS_ENABLED 0x0002#define DF_REMOVABLE_MEDIA 0x0004/* capability bit definitions */#define CAPABILITY_DMA 0x01#define CAPABILITY_LBA 0x02/* command_setX bit definitions */#define COMMANDSET_REMOVABLE 0x02#define COMMANDSET_MEDIA_STATUS 0x10/* ATA Vendor Specific defines */#define ATA_ADDRESS_DEVHEAD_STD 0xa0#define ATA_ADDRESS_DEVHEAD_LBA_MODE 0x40 #define ATA_ADDRESS_DEVHEAD_SLAVE 0x10/* Action Select bits */#define ACTION_SELECT_0 0x01#define ACTION_SELECT_1 0x02#define ACTION_SELECT_2 0x04#define ACTION_SELECT_3 0x08#define ACTION_SELECT_4 0x10#define ACTION_SELECT_5 0x20#define ACTION_SELECT_6 0x40#define ACTION_SELECT_7 0x80/* ATA error definitions not in <linux/hdreg.h> */#define ATA_ERROR_MEDIA_CHANGE 0x20/* ATA command definitions not in <linux/hdreg.h> */#define ATA_COMMAND_GET_MEDIA_STATUS 0xDA#define ATA_COMMAND_MEDIA_EJECT 0xED/* ATA drive control definitions */#define ATA_DC_DISABLE_INTERRUPTS 0x02#define ATA_DC_RESET_CONTROLLER 0x04#define ATA_DC_REENABLE_CONTROLLER 0x00/* * General purpose return codes */ #define ISD200_ERROR -1#define ISD200_GOOD 0/* * Transport return codes */#define ISD200_TRANSPORT_GOOD 0 /* Transport good, command good */#define ISD200_TRANSPORT_FAILED 1 /* Transport good, command failed */#define ISD200_TRANSPORT_ERROR 2 /* Transport bad (i.e. device dead) */#define ISD200_TRANSPORT_ABORTED 3 /* Transport aborted */#define ISD200_TRANSPORT_SHORT 4 /* Transport short *//* driver action codes */#define ACTION_READ_STATUS 0#define ACTION_RESET 1#define ACTION_REENABLE 2#define ACTION_SOFT_RESET 3#define ACTION_ENUM 4#define ACTION_IDENTIFY 5/* * ata_cdb struct */union ata_cdb { struct { unsigned char SignatureByte0; unsigned char SignatureByte1; unsigned char ActionSelect; unsigned char RegisterSelect; unsigned char TransferBlockSize; unsigned char WriteData3F6; unsigned char WriteData1F1; unsigned char WriteData1F2; unsigned char WriteData1F3; unsigned char WriteData1F4; unsigned char WriteData1F5; unsigned char WriteData1F6; unsigned char WriteData1F7; unsigned char Reserved[3]; } generic; struct { unsigned char SignatureByte0; unsigned char SignatureByte1; unsigned char ReadRegisterAccessBit : 1; unsigned char NoDeviceSelectionBit : 1; unsigned char NoBSYPollBit : 1; unsigned char IgnorePhaseErrorBit : 1; unsigned char IgnoreDeviceErrorBit : 1; unsigned char Reserved0Bit : 3; unsigned char SelectAlternateStatus : 1; unsigned char SelectError : 1; unsigned char SelectSectorCount : 1; unsigned char SelectSectorNumber : 1; unsigned char SelectCylinderLow : 1; unsigned char SelectCylinderHigh : 1; unsigned char SelectDeviceHead : 1; unsigned char SelectStatus : 1; unsigned char TransferBlockSize; unsigned char AlternateStatusByte; unsigned char ErrorByte; unsigned char SectorCountByte; unsigned char SectorNumberByte; unsigned char CylinderLowByte; unsigned char CylinderHighByte; unsigned char DeviceHeadByte; unsigned char StatusByte; unsigned char Reserved[3]; } read; struct { unsigned char SignatureByte0; unsigned char SignatureByte1; unsigned char ReadRegisterAccessBit : 1; unsigned char NoDeviceSelectionBit : 1; unsigned char NoBSYPollBit : 1; unsigned char IgnorePhaseErrorBit : 1; unsigned char IgnoreDeviceErrorBit : 1; unsigned char Reserved0Bit : 3; unsigned char SelectDeviceControl : 1; unsigned char SelectFeatures : 1; unsigned char SelectSectorCount : 1; unsigned char SelectSectorNumber : 1; unsigned char SelectCylinderLow : 1; unsigned char SelectCylinderHigh : 1; unsigned char SelectDeviceHead : 1; unsigned char SelectCommand : 1; unsigned char TransferBlockSize; unsigned char DeviceControlByte; unsigned char FeaturesByte; unsigned char SectorCountByte; unsigned char SectorNumberByte; unsigned char CylinderLowByte; unsigned char CylinderHighByte; unsigned char DeviceHeadByte; unsigned char CommandByte; unsigned char Reserved[3]; } write;};/* * Inquiry data structure. This is the data returned from the target * after it receives an inquiry. * * This structure may be extended by the number of bytes specified * in the field AdditionalLength. The defined size constant only * includes fields through ProductRevisionLevel. */struct inquiry_data { unsigned char DeviceType : 5; unsigned char DeviceTypeQualifier : 3; unsigned char DeviceTypeModifier : 7; unsigned char RemovableMedia : 1; unsigned char Versions; unsigned char ResponseDataFormat : 4; unsigned char HiSupport : 1; unsigned char NormACA : 1; unsigned char ReservedBit : 1; unsigned char AERC : 1; unsigned char AdditionalLength; unsigned char Reserved[2]; unsigned char SoftReset : 1; unsigned char CommandQueue : 1; unsigned char Reserved2 : 1; unsigned char LinkedCommands : 1; unsigned char Synchronous : 1; unsigned char Wide16Bit : 1; unsigned char Wide32Bit : 1; unsigned char RelativeAddressing : 1; unsigned char VendorId[8]; unsigned char ProductId[16]; unsigned char ProductRevisionLevel[4]; unsigned char VendorSpecific[20]; unsigned char Reserved3[40];} __attribute__ ((packed));/* * INQUIRY data buffer size */#define INQUIRYDATABUFFERSIZE 36/* * ISD200 CONFIG data struct */struct isd200_config { unsigned char EventNotification; unsigned char ExternalClock; unsigned char ATAInitTimeout; unsigned char ATATiming : 4; unsigned char ATAPIReset : 1; unsigned char MasterSlaveSelection : 1; unsigned char ATAPICommandBlockSize : 2; unsigned char ATAMajorCommand; unsigned char ATAMinorCommand; unsigned char LastLUNIdentifier : 3; unsigned char DescriptOverride : 1; unsigned char ATA3StateSuspend : 1; unsigned char SkipDeviceBoot : 1; unsigned char ConfigDescriptor2 : 1; unsigned char InitStatus : 1; unsigned char SRSTEnable : 1; unsigned char Reserved0 : 7;};/* * ISD200 driver information struct */struct isd200_info { struct inquiry_data InquiryData; struct hd_driveid drive; struct isd200_config ConfigData; unsigned char ATARegs[8]; unsigned char DeviceHead; unsigned char DeviceFlags; /* maximum number of LUNs supported */ unsigned char MaxLUNs;};/* * Read Capacity Data - returned in Big Endian format */struct read_capacity_data { unsigned long LogicalBlockAddress; unsigned long BytesPerBlock;};/* * Read Block Limits Data - returned in Big Endian format * This structure returns the maximum and minimum block * size for a TAPE device. */struct read_block_limits { unsigned char Reserved; unsigned char BlockMaximumSize[3]; unsigned char BlockMinimumSize[2];};/* * Sense Data Format */struct sense_data { unsigned char ErrorCode:7; unsigned char Valid:1; unsigned char SegmentNumber; unsigned char SenseKey:4; unsigned char Reserved:1; unsigned char IncorrectLength:1; unsigned char EndOfMedia:1; unsigned char FileMark:1; unsigned char Information[4]; unsigned char AdditionalSenseLength; unsigned char CommandSpecificInformation[4]; unsigned char AdditionalSenseCode; unsigned char AdditionalSenseCodeQualifier; unsigned char FieldReplaceableUnitCode; unsigned char SenseKeySpecific[3];} __attribute__ ((packed));/* * Default request sense buffer size */#define SENSE_BUFFER_SIZE 18/*********************************************************************** * Helper routines ***********************************************************************//************************************************************************** * isd200_build_sense * * Builds an artificial sense buffer to report the results of a * failed command. * * RETURNS: * void */ void isd200_build_sense(struct us_data *us, Scsi_Cmnd *srb){ struct isd200_info *info = (struct isd200_info *)us->extra; struct sense_data *buf = (struct sense_data *) &srb->sense_buffer[0]; unsigned char error = info->ATARegs[IDE_ERROR_OFFSET]; if(error & ATA_ERROR_MEDIA_CHANGE) { buf->ErrorCode = 0x70; buf->Valid = 1; buf->AdditionalSenseLength = 0xb; buf->SenseKey = UNIT_ATTENTION; buf->AdditionalSenseCode = 0; buf->AdditionalSenseCodeQualifier = 0; } else if(error & MCR_ERR) { buf->ErrorCode = 0x70; buf->Valid = 1; buf->AdditionalSenseLength = 0xb; buf->SenseKey = UNIT_ATTENTION; buf->AdditionalSenseCode = 0; buf->AdditionalSenseCodeQualifier = 0; } else if(error & TRK0_ERR) { buf->ErrorCode = 0x70; buf->Valid = 1; buf->AdditionalSenseLength = 0xb; buf->SenseKey = NOT_READY; buf->AdditionalSenseCode = 0; buf->AdditionalSenseCodeQualifier = 0; } else if(error & ECC_ERR) { buf->ErrorCode = 0x70; buf->Valid = 1; buf->AdditionalSenseLength = 0xb; buf->SenseKey = DATA_PROTECT; buf->AdditionalSenseCode = 0; buf->AdditionalSenseCodeQualifier = 0; } else { buf->ErrorCode = 0; buf->Valid = 0; buf->AdditionalSenseLength = 0; buf->SenseKey = 0; buf->AdditionalSenseCode = 0; buf->AdditionalSenseCodeQualifier = 0; }}/*********************************************************************** * Data transfer routines ***********************************************************************//************************************************************************** * Transfer one SCSI scatter-gather buffer via bulk transfer * * Note that this function is necessary because we want the ability to * use scatter-gather memory. Good performance is achieved by a combination * of scatter-gather and clustering (which makes each chunk bigger). * * Note that the lower layer will always retry when a NAK occurs, up to the * timeout limit. Thus we don't have to worry about it for individual * packets. */static int isd200_transfer_partial( struct us_data *us, unsigned char dataDirection, char *buf, int length ){ int result; int partial; int pipe; /* calculate the appropriate pipe information */ if (dataDirection == SCSI_DATA_READ) pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); else pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); /* transfer the data */ US_DEBUGP("isd200_transfer_partial(): xfer %d bytes\n", length); result = usb_stor_bulk_msg(us, buf, pipe, length, &partial);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -