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

📄 isd200.c

📁 LINUX下USB驱动程序的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
				 * 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 (info->drive.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*)info->drive.model;				dest = (__u16*)info->InquiryData.VendorId;				for (i=0;i<4;i++)					dest[i] = be16_to_cpu(src[i]);				src = (__u16*)(info->drive.model+8);				dest = (__u16*)info->InquiryData.ProductId;				for (i=0;i<8;i++)					dest[i] = be16_to_cpu(src[i]);				src = (__u16*)info->drive.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 (info->drive.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 */            			if (us->extra != NULL) {				kfree(us->extra);				us->extra = NULL;				us->extra_destructor = NULL;			}		}        }	US_DEBUGP("Leaving isd200_get_inquiry_data %08X\n", retStatus);	return(retStatus);}/************************************************************************** * isd200_data_copy *                                                                          * Copy data into the srb request buffer.  Use scatter gather if required. * * RETURNS: *    void */                                                                        void isd200_data_copy(Scsi_Cmnd *srb, char * src, int length){	unsigned int len = length;	struct scatterlist *sg;	if (srb->use_sg) {		int i;		unsigned int total = 0;		/* Add up the sizes of all the sg segments */		sg = (struct scatterlist *) srb->request_buffer;		for (i = 0; i < srb->use_sg; i++)			total += sg[i].length;		if (length > total)			len = total;		total = 0;		/* Copy data into sg buffer(s) */		for (i = 0; i < srb->use_sg; i++) {			if ((len > total) && (len > 0)) {				/* transfer the lesser of the next buffer or the				 * remaining data */				if (len - total >= sg[i].length) {					memcpy(sg[i].address, src + total, sg[i].length);					total += sg[i].length;				} else {					memcpy(sg[i].address, src + total, len - total);					total = len;				}			} 			else				break;		}	} else	{		/* Make sure length does not exceed buffer length */		if (length > srb->request_bufflen)			len = srb->request_bufflen;		if (len > 0)			memcpy(srb->request_buffer, src, len);	}}/************************************************************************** * 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 */                                                                        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;	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");		if (srb->request_bufflen > sizeof(struct inquiry_data))			srb->request_bufflen = sizeof(struct inquiry_data);		/* copy InquiryData */		isd200_data_copy(srb, (char *) &info->InquiryData, srb->request_bufflen);		srb->result = GOOD;		sendToTransport = FALSE;		break;	case MODE_SENSE:		US_DEBUGP("   ATA OUT - SCSIOP_MODE_SENSE\n");		/* Initialize the return buffer */		isd200_data_copy(srb, (char *) &senseData, 8);		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 = WIN_GETMEDIASTATUS;			srb->request_bufflen = 0;		} else {			US_DEBUGP("   Media Status not supported, just report okay\n");			srb->result = GOOD;			sendToTransport = FALSE;		}		break;	case TEST_UNIT_READY:		US_DEBUGP("   ATA OUT - SCSIOP_TEST_UNIT_READY\n");		/* Initialize the return buffer */		isd200_data_copy(srb, (char *) &senseData, 8);		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 = WIN_GETMEDIASTATUS;			srb->request_bufflen = 0;		} else {			US_DEBUGP("   Media Status not supported, just report okay\n");			srb->result = GOOD;			sendToTransport = FALSE;		}		break;	case READ_CAPACITY:	{		unsigned long capacity;		struct read_capacity_data readCapacityData;		US_DEBUGP("   ATA OUT - SCSIOP_READ_CAPACITY\n");		if (info->drive.capability & CAPABILITY_LBA ) {			capacity = info->drive.lba_capacity - 1;		} else {			capacity = (info->drive.heads *				    info->drive.cyls *				    info->drive.sectors) - 1;		}		readCapacityData.LogicalBlockAddress = cpu_to_be32(capacity);		readCapacityData.BytesPerBlock = cpu_to_be32(0x200);		if (srb->request_bufflen > sizeof(struct read_capacity_data))			srb->request_bufflen = sizeof(struct read_capacity_data);		isd200_data_copy(srb, (char *) &readCapacityData, srb->request_bufflen);		srb->result = 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 (info->drive.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 % info->drive.sectors) + 1);			cylinder = (unsigned short)(lba / (info->drive.sectors *							   info->drive.heads));			head = (unsigned char)((lba / info->drive.sectors) %					       info->drive.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 (info->drive.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 % info->drive.sectors) + 1);			cylinder = (unsigned short)(lba / (info->drive.sectors * info->drive.heads));			head = (unsigned char)((lba / info->drive.sectors) % info->drive.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 = 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]);		/* Initialize the return buffer */		isd200_data_copy(srb, (char *) &senseData, 8);		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 = WIN_MEDIAEJECT;		} 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 = WIN_GETMEDIASTATUS;			srb->request_bufflen = 0;		} else {			US_DEBUGP("   Nothing to do, just report okay\n");			srb->result = 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_init_info *                                                                          * Allocates (if necessary) and initializes the driver structure. * * RETURNS: *    ISD status code */                                                                        int isd200_init_info(struct us_data *us){	int retStatus = ISD200_GOOD;	if (!us->extra) {		us->extra = (void *) kmalloc(sizeof(struct isd200_info), GFP_KERNEL);		if (!us->extra) {			US_DEBUGP("ERROR - kmalloc failure\n");			retStatus = ISD200_ERROR;		}        }	if (retStatus == ISD200_GOOD) {		memset(us->extra, 0, sizeof(struct isd200_info));        }	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 */	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 + -