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

📄 isd200.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* 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 + -