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

📄 isd200.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Transport & Protocol Driver for In-System Design, Inc. ISD200 ASIC * * $Id: isd200.c,v 1.16 2002/04/22 03:39:43 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: * *  2002-10-19: Removed the specialized transfer routines. *		(Alan Stern <stern@rowland.harvard.edu>) *  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/jiffies.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 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) *//* 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 *id;	struct isd200_config ConfigData;	unsigned char *RegsBuf;	unsigned char ATARegs[8];	unsigned char DeviceHead;	unsigned char DeviceFlags;	/* maximum number of LUNs supported */	unsigned char MaxLUNs;	struct scsi_cmnd srb;};/* * 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 */static 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 | 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;	}}/*********************************************************************** * 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 = SCSI_DATA_READ;		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 = SCSI_DATA_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 = SCSI_DATA_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 = SCSI_DATA_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 = SCSI_DATA_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 = SCSI_DATA_READ;		srb->request_buffer = (void *) info->id;		srb->request_bufflen = sizeof(struct hd_driveid);		break;	default:		US_DEBUGP("Error: Undefined action %d\n",action);

⌨️ 快捷键说明

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