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

📄 isd200.c

📁 LINUX下USB驱动程序的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Transport & Protocol Driver for In-System Design, Inc. ISD200 ASIC * * $Id: isd200.c,v 1.14 2002/02/25 00:40:13 mdharm Exp $ * * Current development and maintenance: *   (C) 2001-2002 Bj鰎n Stenberg (bjorn@haxx.se) * * Developed with the assistance of: *   (C) 2002 Alan Stern <stern@rowland.org> * * Initial work: *   (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) *  2002-01-16: Fixed endianness bug so it works on the ppc arch. *              (Luc Saillard <luc@saillard.org>) *  2002-01-17: All bitfields removed. *              (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>/* 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/* Register Select bits */#define REG_ALTERNATE_STATUS 0x01#define REG_DEVICE_CONTROL   0x01#define REG_ERROR            0x02#define REG_FEATURES         0x02#define REG_SECTOR_COUNT     0x04#define REG_SECTOR_NUMBER    0x08#define REG_CYLINDER_LOW     0x10#define REG_CYLINDER_HIGH    0x20#define REG_DEVICE_HEAD      0x40#define REG_STATUS           0x80#define REG_COMMAND          0x80/* 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 ActionSelect;		unsigned char RegisterSelect;		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 ActionSelect;		unsigned char RegisterSelect;		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. *//* * DeviceType field */#define DIRECT_ACCESS_DEVICE            0x00    /* disks */#define DEVICE_REMOVABLE                0x80struct inquiry_data {   	unsigned char DeviceType;	unsigned char DeviceTypeModifier;	unsigned char Versions;	unsigned char Format; 	unsigned char AdditionalLength;	unsigned char Reserved[2];	unsigned char Capability;	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 */#define ATACFG_TIMING          0x0f#define ATACFG_ATAPI_RESET     0x10#define ATACFG_MASTER          0x20#define ATACFG_BLOCKSIZE       0xa0#define ATACFGE_LAST_LUN       0x07#define ATACFGE_DESC_OVERRIDE  0x08#define ATACFGE_STATE_SUSPEND  0x10#define ATACFGE_SKIP_BOOT      0x20#define ATACFGE_CONF_DESC2     0x40#define ATACFGE_INIT_STATUS    0x80#define CFG_CAPABILITY_SRST    0x01struct isd200_config {        unsigned char EventNotification;        unsigned char ExternalClock;        unsigned char ATAInitTimeout;	unsigned char ATAConfig;        unsigned char ATAMajorCommand;        unsigned char ATAMinorCommand;	unsigned char ATAExtraConfig;	unsigned char Capability;}__attribute__ ((packed));/* * 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 */#define SENSE_ERRCODE           0x7f#define SENSE_ERRCODE_VALID     0x80#define SENSE_FLAG_SENSE_KEY    0x0f#define SENSE_FLAG_BAD_LENGTH   0x20#define SENSE_FLAG_END_OF_MEDIA 0x40#define SENSE_FLAG_FILE_MARK    0x80struct sense_data {	unsigned char ErrorCode;	unsigned char SegmentNumber;	unsigned char Flags;        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 & MC_ERR) {		buf->ErrorCode = 0x70 | SENSE_ERRCODE_VALID;		buf->AdditionalSenseLength = 0xb;		buf->Flags = UNIT_ATTENTION;		buf->AdditionalSenseCode = 0;		buf->AdditionalSenseCodeQualifier = 0;        } else if(error & MCR_ERR) {		buf->ErrorCode = 0x70 | SENSE_ERRCODE_VALID;		buf->AdditionalSenseLength = 0xb;		buf->Flags =  UNIT_ATTENTION;		buf->AdditionalSenseCode = 0;		buf->AdditionalSenseCodeQualifier = 0;        } else if(error & TRK0_ERR) {		buf->ErrorCode = 0x70 | SENSE_ERRCODE_VALID;		buf->AdditionalSenseLength = 0xb;		buf->Flags =  NOT_READY;		buf->AdditionalSenseCode = 0;		buf->AdditionalSenseCodeQualifier = 0;        } else if(error & ECC_ERR) {		buf->ErrorCode = 0x70 | SENSE_ERRCODE_VALID;		buf->AdditionalSenseLength = 0xb;		buf->Flags =  DATA_PROTECT;		buf->AdditionalSenseCode = 0;		buf->AdditionalSenseCodeQualifier = 0;        } else {		buf->ErrorCode = 0;		buf->AdditionalSenseLength = 0;		buf->Flags =  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);        US_DEBUGP("usb_stor_bulk_msg() returned %d xferred %d/%d\n",                  result, partial, length);        /* if we stall, we need to clear it before we go on */        if (result == -EPIPE) {                US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);                usb_stor_clear_halt(us, pipe);        }            /* did we send all the data? */        if (partial == length) {                US_DEBUGP("isd200_transfer_partial(): transfer complete\n");                return ISD200_TRANSPORT_GOOD;        }        /* uh oh... we have an error code, so something went wrong. */        if (result) {                /* NAK - that means we've retried a few times already */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -