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

📄 isd200.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			info->ConfigData.ATAConfig &= 0x3f;			info->ConfigData.ATAConfig |= (isslave<<6);			retStatus = isd200_write_config(us);		}	}	US_DEBUGP("Leaving isd200_manual_enum %08X\n", retStatus);	return(retStatus);}/************************************************************************** * isd200_get_inquiry_data * * Get inquiry data * * RETURNS: *    ISD status code */static int isd200_get_inquiry_data( struct us_data *us ){	struct isd200_info *info = (struct isd200_info *)us->extra;	int retStatus = ISD200_GOOD;	struct hd_driveid *id = info->id;	US_DEBUGP("Entering isd200_get_inquiry_data\n");	/* set default to Master */	info->DeviceHead = ATA_ADDRESS_DEVHEAD_STD;	/* attempt to manually enumerate this device */	retStatus = isd200_manual_enum(us);	if (retStatus == ISD200_GOOD) {		int transferStatus;		/* check for an ATA device */		if (info->DeviceFlags & DF_ATA_DEVICE) {			/* this must be an ATA device */			/* perform an ATA Command Identify */			transferStatus = isd200_action( us, ACTION_IDENTIFY,							id, 							sizeof(struct hd_driveid) );			if (transferStatus != ISD200_TRANSPORT_GOOD) {				/* Error issuing ATA Command Identify */				US_DEBUGP("   Error issuing ATA Command Identify\n");				retStatus = ISD200_ERROR;			} else {				/* ATA Command Identify successful */				int i;				__u16 *src, *dest;				ide_fix_driveid(id);				US_DEBUGP("   Identify Data Structure:\n");				US_DEBUGP("      config = 0x%x\n", id->config);				US_DEBUGP("      cyls = 0x%x\n", id->cyls);				US_DEBUGP("      heads = 0x%x\n", id->heads);				US_DEBUGP("      track_bytes = 0x%x\n", id->track_bytes);				US_DEBUGP("      sector_bytes = 0x%x\n", id->sector_bytes);				US_DEBUGP("      sectors = 0x%x\n", id->sectors);				US_DEBUGP("      serial_no[0] = 0x%x\n", id->serial_no[0]);				US_DEBUGP("      buf_type = 0x%x\n", id->buf_type);				US_DEBUGP("      buf_size = 0x%x\n", id->buf_size);				US_DEBUGP("      ecc_bytes = 0x%x\n", id->ecc_bytes);				US_DEBUGP("      fw_rev[0] = 0x%x\n", id->fw_rev[0]);				US_DEBUGP("      model[0] = 0x%x\n", id->model[0]);				US_DEBUGP("      max_multsect = 0x%x\n", id->max_multsect);				US_DEBUGP("      dword_io = 0x%x\n", id->dword_io);				US_DEBUGP("      capability = 0x%x\n", id->capability);				US_DEBUGP("      tPIO = 0x%x\n", id->tPIO);				US_DEBUGP("      tDMA = 0x%x\n", id->tDMA);				US_DEBUGP("      field_valid = 0x%x\n", id->field_valid);				US_DEBUGP("      cur_cyls = 0x%x\n", id->cur_cyls);				US_DEBUGP("      cur_heads = 0x%x\n", id->cur_heads);				US_DEBUGP("      cur_sectors = 0x%x\n", id->cur_sectors);				US_DEBUGP("      cur_capacity = 0x%x\n", (id->cur_capacity1 << 16) + id->cur_capacity0 );				US_DEBUGP("      multsect = 0x%x\n", id->multsect);				US_DEBUGP("      lba_capacity = 0x%x\n", id->lba_capacity);				US_DEBUGP("      command_set_1 = 0x%x\n", id->command_set_1);				US_DEBUGP("      command_set_2 = 0x%x\n", id->command_set_2);				memset(&info->InquiryData, 0, sizeof(info->InquiryData));				/* Standard IDE interface only supports disks */				info->InquiryData.DeviceType = DIRECT_ACCESS_DEVICE;				/* Fix-up the return data from an INQUIRY command to show 				 * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us				 * in Linux.				 */				info->InquiryData.Versions = 0x2;				/* The length must be at least 36 (5 + 31) */				info->InquiryData.AdditionalLength = 0x1F;				if (id->command_set_1 & COMMANDSET_MEDIA_STATUS) {					/* set the removable bit */					info->InquiryData.DeviceTypeModifier = DEVICE_REMOVABLE;					info->DeviceFlags |= DF_REMOVABLE_MEDIA;				}				/* Fill in vendor identification fields */				src = (__u16*)id->model;				dest = (__u16*)info->InquiryData.VendorId;				for (i=0;i<4;i++)					dest[i] = be16_to_cpu(src[i]);				src = (__u16*)(id->model+8);				dest = (__u16*)info->InquiryData.ProductId;				for (i=0;i<8;i++)					dest[i] = be16_to_cpu(src[i]);				src = (__u16*)id->fw_rev;				dest = (__u16*)info->InquiryData.ProductRevisionLevel;				for (i=0;i<2;i++)					dest[i] = be16_to_cpu(src[i]);				/* determine if it supports Media Status Notification */				if (id->command_set_2 & COMMANDSET_MEDIA_STATUS) {					US_DEBUGP("   Device supports Media Status Notification\n");					/* Indicate that it is enabled, even though it is not					 * This allows the lock/unlock of the media to work					 * correctly.					 */					info->DeviceFlags |= DF_MEDIA_STATUS_ENABLED;				}				else					info->DeviceFlags &= ~DF_MEDIA_STATUS_ENABLED;			}		} else {			/* 			 * this must be an ATAPI device 			 * use an ATAPI protocol (Transparent SCSI)			 */			us->protocol_name = "Transparent SCSI";			us->proto_handler = usb_stor_transparent_scsi_command;			US_DEBUGP("Protocol changed to: %s\n", us->protocol_name);	    			/* Free driver structure */	    			us->extra_destructor(info);			us->extra = NULL;			us->extra_destructor = NULL;		}	}	US_DEBUGP("Leaving isd200_get_inquiry_data %08X\n", retStatus);	return(retStatus);}/************************************************************************** * isd200_scsi_to_ata *									  * Translate SCSI commands to ATA commands. * * RETURNS: *    TRUE if the command needs to be sent to the transport layer *    FALSE otherwise */static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,			      union ata_cdb * ataCdb){	struct isd200_info *info = (struct isd200_info *)us->extra;	struct hd_driveid *id = info->id;	int sendToTransport = TRUE;	unsigned char sectnum, head;	unsigned short cylinder;	unsigned long lba;	unsigned long blockCount;	unsigned char senseData[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };	memset(ataCdb, 0, sizeof(union ata_cdb));	/* SCSI Command */	switch (srb->cmnd[0]) {	case INQUIRY:		US_DEBUGP("   ATA OUT - INQUIRY\n");		/* copy InquiryData */		usb_stor_set_xfer_buf((unsigned char *) &info->InquiryData,				sizeof(info->InquiryData), srb);		srb->result = SAM_STAT_GOOD;		sendToTransport = FALSE;		break;	case MODE_SENSE:		US_DEBUGP("   ATA OUT - SCSIOP_MODE_SENSE\n");		/* Initialize the return buffer */		usb_stor_set_xfer_buf(senseData, sizeof(senseData), srb);		if (info->DeviceFlags & DF_MEDIA_STATUS_ENABLED)		{			ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;			ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;			ataCdb->generic.TransferBlockSize = 1;			ataCdb->generic.RegisterSelect = REG_COMMAND;			ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;			srb->request_bufflen = 0;		} else {			US_DEBUGP("   Media Status not supported, just report okay\n");			srb->result = SAM_STAT_GOOD;			sendToTransport = FALSE;		}		break;	case TEST_UNIT_READY:		US_DEBUGP("   ATA OUT - SCSIOP_TEST_UNIT_READY\n");		if (info->DeviceFlags & DF_MEDIA_STATUS_ENABLED)		{			ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;			ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;			ataCdb->generic.TransferBlockSize = 1;			ataCdb->generic.RegisterSelect = REG_COMMAND;			ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;			srb->request_bufflen = 0;		} else {			US_DEBUGP("   Media Status not supported, just report okay\n");			srb->result = SAM_STAT_GOOD;			sendToTransport = FALSE;		}		break;	case READ_CAPACITY:	{		unsigned long capacity;		struct read_capacity_data readCapacityData;		US_DEBUGP("   ATA OUT - SCSIOP_READ_CAPACITY\n");		if (id->capability & CAPABILITY_LBA ) {			capacity = id->lba_capacity - 1;		} else {			capacity = (id->heads *				    id->cyls *				    id->sectors) - 1;		}		readCapacityData.LogicalBlockAddress = cpu_to_be32(capacity);		readCapacityData.BytesPerBlock = cpu_to_be32(0x200);		usb_stor_set_xfer_buf((unsigned char *) &readCapacityData,				sizeof(readCapacityData), srb);		srb->result = SAM_STAT_GOOD;		sendToTransport = FALSE;	}	break;	case READ_10:		US_DEBUGP("   ATA OUT - SCSIOP_READ\n");		lba = *(unsigned long *)&srb->cmnd[2]; 		lba = cpu_to_be32(lba);		blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8];		if (id->capability & CAPABILITY_LBA) {			sectnum = (unsigned char)(lba);			cylinder = (unsigned short)(lba>>8);			head = ATA_ADDRESS_DEVHEAD_LBA_MODE | (unsigned char)(lba>>24 & 0x0F);		} else {			sectnum = (unsigned char)((lba % id->sectors) + 1);			cylinder = (unsigned short)(lba / (id->sectors *							   id->heads));			head = (unsigned char)((lba / id->sectors) %					       id->heads);		}		ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;		ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;		ataCdb->generic.TransferBlockSize = 1;		ataCdb->generic.RegisterSelect =		  REG_SECTOR_COUNT | REG_SECTOR_NUMBER |		  REG_CYLINDER_LOW | REG_CYLINDER_HIGH |		  REG_DEVICE_HEAD  | REG_COMMAND;		ataCdb->write.SectorCountByte = (unsigned char)blockCount;		ataCdb->write.SectorNumberByte = sectnum;		ataCdb->write.CylinderHighByte = (unsigned char)(cylinder>>8);		ataCdb->write.CylinderLowByte = (unsigned char)cylinder;		ataCdb->write.DeviceHeadByte = (head | ATA_ADDRESS_DEVHEAD_STD);		ataCdb->write.CommandByte = WIN_READ;		break;	case WRITE_10:		US_DEBUGP("   ATA OUT - SCSIOP_WRITE\n");		lba = *(unsigned long *)&srb->cmnd[2]; 		lba = cpu_to_be32(lba);		blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8];		if (id->capability & CAPABILITY_LBA) {			sectnum = (unsigned char)(lba);			cylinder = (unsigned short)(lba>>8);			head = ATA_ADDRESS_DEVHEAD_LBA_MODE | (unsigned char)(lba>>24 & 0x0F);		} else {			sectnum = (unsigned char)((lba % id->sectors) + 1);			cylinder = (unsigned short)(lba / (id->sectors * id->heads));			head = (unsigned char)((lba / id->sectors) % id->heads);		}		ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;		ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;		ataCdb->generic.TransferBlockSize = 1;		ataCdb->generic.RegisterSelect =		  REG_SECTOR_COUNT | REG_SECTOR_NUMBER |		  REG_CYLINDER_LOW | REG_CYLINDER_HIGH |		  REG_DEVICE_HEAD  | REG_COMMAND;		ataCdb->write.SectorCountByte = (unsigned char)blockCount;		ataCdb->write.SectorNumberByte = sectnum;		ataCdb->write.CylinderHighByte = (unsigned char)(cylinder>>8);		ataCdb->write.CylinderLowByte = (unsigned char)cylinder;		ataCdb->write.DeviceHeadByte = (head | ATA_ADDRESS_DEVHEAD_STD);		ataCdb->write.CommandByte = WIN_WRITE;		break;	case ALLOW_MEDIUM_REMOVAL:		US_DEBUGP("   ATA OUT - SCSIOP_MEDIUM_REMOVAL\n");		if (info->DeviceFlags & DF_REMOVABLE_MEDIA) {			US_DEBUGP("   srb->cmnd[4] = 0x%X\n", srb->cmnd[4]);	    			ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;			ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;			ataCdb->generic.TransferBlockSize = 1;			ataCdb->generic.RegisterSelect = REG_COMMAND;			ataCdb->write.CommandByte = (srb->cmnd[4] & 0x1) ?				WIN_DOORLOCK : WIN_DOORUNLOCK;			srb->request_bufflen = 0;		} else {			US_DEBUGP("   Not removeable media, just report okay\n");			srb->result = SAM_STAT_GOOD;			sendToTransport = FALSE;		}		break;	case START_STOP:    		US_DEBUGP("   ATA OUT - SCSIOP_START_STOP_UNIT\n");		US_DEBUGP("   srb->cmnd[4] = 0x%X\n", srb->cmnd[4]);		if ((srb->cmnd[4] & 0x3) == 0x2) {			US_DEBUGP("   Media Eject\n");			ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;			ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;			ataCdb->generic.TransferBlockSize = 0;			ataCdb->generic.RegisterSelect = REG_COMMAND;			ataCdb->write.CommandByte = ATA_COMMAND_MEDIA_EJECT;		} else if ((srb->cmnd[4] & 0x3) == 0x1) {			US_DEBUGP("   Get Media Status\n");			ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;			ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;			ataCdb->generic.TransferBlockSize = 1;			ataCdb->generic.RegisterSelect = REG_COMMAND;			ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;			srb->request_bufflen = 0;		} else {			US_DEBUGP("   Nothing to do, just report okay\n");			srb->result = SAM_STAT_GOOD;			sendToTransport = FALSE;		}		break;	default:		US_DEBUGP("Unsupported SCSI command - 0x%X\n", srb->cmnd[0]);		srb->result = DID_ERROR << 16;		sendToTransport = FALSE;		break;	}	return(sendToTransport);}/************************************************************************** * isd200_free_info * * Frees the driver structure. */static void isd200_free_info_ptrs(void *info_){	struct isd200_info *info = (struct isd200_info *) info_;	if (info) {		kfree(info->id);		kfree(info->RegsBuf);	}}/************************************************************************** * isd200_init_info *									  * Allocates (if necessary) and initializes the driver structure. * * RETURNS: *    ISD status code */static int isd200_init_info(struct us_data *us){	int retStatus = ISD200_GOOD;	struct isd200_info *info;	info = (struct isd200_info *)			kmalloc(sizeof(struct isd200_info), GFP_KERNEL);	if (!info)		retStatus = ISD200_ERROR;	else {		memset(info, 0, sizeof(struct isd200_info));		info->id = (struct hd_driveid *)				kmalloc(sizeof(struct hd_driveid), GFP_KERNEL);		info->RegsBuf = (unsigned char *)				kmalloc(sizeof(info->ATARegs), GFP_KERNEL);		if (!info->id || !info->RegsBuf) {			isd200_free_info_ptrs(info);			kfree(info);			retStatus = ISD200_ERROR;		} else			memset(info->id, 0, sizeof(struct hd_driveid));	}	if (retStatus == ISD200_GOOD) {		us->extra = info;		us->extra_destructor = isd200_free_info_ptrs;	} else		US_DEBUGP("ERROR - kmalloc failure\n");	return(retStatus);}/************************************************************************** * Initialization for the ISD200  */int isd200_Initialization(struct us_data *us){	US_DEBUGP("ISD200 Initialization...\n");	/* Initialize ISD200 info struct */	if (isd200_init_info(us) == ISD200_ERROR) {		US_DEBUGP("ERROR Initializing ISD200 Info struct\n");	} else {		/* Get device specific data */		if (isd200_get_inquiry_data(us) != ISD200_GOOD)			US_DEBUGP("ISD200 Initialization Failure\n");		else			US_DEBUGP("ISD200 Initialization complete\n");	}	return 0;}/************************************************************************** * Protocol and Transport for the ISD200 ASIC * * This protocol and transport are for ATA devices connected to an ISD200 * ASIC.  An ATAPI device that is conected as a slave device will be * detected in the driver initialization function and the protocol will * be changed to an ATAPI protocol (Transparent SCSI). * */void isd200_ata_command(Scsi_Cmnd *srb, struct us_data *us){	int sendToTransport = TRUE;	union ata_cdb ataCdb;	/* Make sure driver was initialized */	if (us->extra == NULL)		US_DEBUGP("ERROR Driver not initialized\n");	/* Convert command */	srb->resid = 0;	sendToTransport = isd200_scsi_to_ata(srb, us, &ataCdb);	/* send the command to the transport layer */	if (sendToTransport)		isd200_invoke_transport(us, srb, &ataCdb);}

⌨️ 快捷键说明

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