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

📄 shuttle_usbat.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* The setup command */	result = usbat_execute_command(us, command, 8);	if (result != USB_STOR_XFER_GOOD)		return USB_STOR_TRANSPORT_ERROR;	/* Create the reg/data, reg/data sequence */	for (i=0; i<num_registers; i++) {		data[i<<1] = registers[i];		data[1+(i<<1)] = data_out[i];	}	/* Send the data */	result = usbat_bulk_write(us, data, num_registers*2);	if (result != USB_STOR_XFER_GOOD)		return USB_STOR_TRANSPORT_ERROR;	if (usbat_get_device_type(us) == USBAT_DEV_HP8200)		return usbat_wait_not_busy(us, 0);	else		return USB_STOR_TRANSPORT_GOOD;}/* * Conditionally read blocks from device: * Allows us to read blocks from a specific data register, based upon the * condition that a status register can be successfully masked with a status * qualifier. If this condition is not initially met, the read will wait * up until a maximum amount of time has elapsed, as specified by timeout. * The read will start when the condition is met, otherwise the command aborts. * * The qualifier defined here is not the value that is masked, it defines * conditions for the write to take place. The actual masked qualifier (and * other related details) are defined beforehand with _set_shuttle_features(). */static int usbat_read_blocks(struct us_data *us,							 unsigned char *buffer,							 int len){	int result;	unsigned char *command = us->iobuf;	command[0] = 0xC0;	command[1] = USBAT_ATA | USBAT_CMD_COND_READ_BLOCK;	command[2] = USBAT_ATA_DATA;	command[3] = USBAT_ATA_STATUS;	command[4] = 0xFD; /* Timeout (ms); */	command[5] = USBAT_QUAL_FCQ;	command[6] = LSB_of(len);	command[7] = MSB_of(len);	/* Multiple block read setup command */	result = usbat_execute_command(us, command, 8);	if (result != USB_STOR_XFER_GOOD)		return USB_STOR_TRANSPORT_FAILED;		/* Read the blocks we just asked for */	result = usbat_bulk_read(us, buffer, len);	if (result != USB_STOR_XFER_GOOD)		return USB_STOR_TRANSPORT_FAILED;	return USB_STOR_TRANSPORT_GOOD;}/* * Conditionally write blocks to device: * Allows us to write blocks to a specific data register, based upon the * condition that a status register can be successfully masked with a status * qualifier. If this condition is not initially met, the write will wait * up until a maximum amount of time has elapsed, as specified by timeout. * The read will start when the condition is met, otherwise the command aborts. * * The qualifier defined here is not the value that is masked, it defines * conditions for the write to take place. The actual masked qualifier (and * other related details) are defined beforehand with _set_shuttle_features(). */static int usbat_write_blocks(struct us_data *us,							  unsigned char *buffer,							  int len){	int result;	unsigned char *command = us->iobuf;	command[0] = 0x40;	command[1] = USBAT_ATA | USBAT_CMD_COND_WRITE_BLOCK;	command[2] = USBAT_ATA_DATA;	command[3] = USBAT_ATA_STATUS;	command[4] = 0xFD; /* Timeout (ms) */	command[5] = USBAT_QUAL_FCQ;	command[6] = LSB_of(len);	command[7] = MSB_of(len);	/* Multiple block write setup command */	result = usbat_execute_command(us, command, 8);	if (result != USB_STOR_XFER_GOOD)		return USB_STOR_TRANSPORT_FAILED;		/* Write the data */	result = usbat_bulk_write(us, buffer, len);	if (result != USB_STOR_XFER_GOOD)		return USB_STOR_TRANSPORT_FAILED;	return USB_STOR_TRANSPORT_GOOD;}/* * Read the User IO register */static int usbat_read_user_io(struct us_data *us, unsigned char *data_flags){	int result;	result = usb_stor_ctrl_transfer(us,		us->recv_ctrl_pipe,		USBAT_CMD_UIO,		0xC0,		0,		0,		data_flags,		USBAT_UIO_READ);	US_DEBUGP("usbat_read_user_io: UIO register reads %02X\n", (unsigned short) (*data_flags));	return result;}/* * Write to the User IO register */static int usbat_write_user_io(struct us_data *us,			       unsigned char enable_flags,			       unsigned char data_flags){	return usb_stor_ctrl_transfer(us,		us->send_ctrl_pipe,		USBAT_CMD_UIO,		0x40,		short_pack(enable_flags, data_flags),		0,		NULL,		USBAT_UIO_WRITE);}/* * Reset the device * Often needed on media change. */static int usbat_device_reset(struct us_data *us){	int rc;	/*	 * Reset peripheral, enable peripheral control signals	 * (bring reset signal up)	 */	rc = usbat_write_user_io(us,							 USBAT_UIO_DRVRST | USBAT_UIO_OE1 | USBAT_UIO_OE0,							 USBAT_UIO_EPAD | USBAT_UIO_1);	if (rc != USB_STOR_XFER_GOOD)		return USB_STOR_TRANSPORT_ERROR;				/*	 * Enable peripheral control signals	 * (bring reset signal down)	 */	rc = usbat_write_user_io(us,							 USBAT_UIO_OE1  | USBAT_UIO_OE0,							 USBAT_UIO_EPAD | USBAT_UIO_1);	if (rc != USB_STOR_XFER_GOOD)		return USB_STOR_TRANSPORT_ERROR;	return USB_STOR_TRANSPORT_GOOD;}/* * Enable card detect */static int usbat_device_enable_cdt(struct us_data *us){	int rc;	/* Enable peripheral control signals and card detect */	rc = usbat_write_user_io(us,							 USBAT_UIO_ACKD | USBAT_UIO_OE1  | USBAT_UIO_OE0,							 USBAT_UIO_EPAD | USBAT_UIO_1);	if (rc != USB_STOR_XFER_GOOD)		return USB_STOR_TRANSPORT_ERROR;	return USB_STOR_TRANSPORT_GOOD;}/* * Determine if media is present. */static int usbat_flash_check_media_present(unsigned char *uio){	if (*uio & USBAT_UIO_UI0) {		US_DEBUGP("usbat_flash_check_media_present: no media detected\n");		return USBAT_FLASH_MEDIA_NONE;	}	return USBAT_FLASH_MEDIA_CF;}/* * Determine if media has changed since last operation */static int usbat_flash_check_media_changed(unsigned char *uio){	if (*uio & USBAT_UIO_0) {		US_DEBUGP("usbat_flash_check_media_changed: media change detected\n");		return USBAT_FLASH_MEDIA_CHANGED;	}	return USBAT_FLASH_MEDIA_SAME;}/* * Check for media change / no media and handle the situation appropriately */static int usbat_flash_check_media(struct us_data *us,				   struct usbat_info *info){	int rc;	unsigned char *uio = us->iobuf;	rc = usbat_read_user_io(us, uio);	if (rc != USB_STOR_XFER_GOOD)		return USB_STOR_TRANSPORT_ERROR;	/* Check for media existence */	rc = usbat_flash_check_media_present(uio);	if (rc == USBAT_FLASH_MEDIA_NONE) {		info->sense_key = 0x02;		info->sense_asc = 0x3A;		info->sense_ascq = 0x00;		return USB_STOR_TRANSPORT_FAILED;	}	/* Check for media change */	rc = usbat_flash_check_media_changed(uio);	if (rc == USBAT_FLASH_MEDIA_CHANGED) {		/* Reset and re-enable card detect */		rc = usbat_device_reset(us);		if (rc != USB_STOR_TRANSPORT_GOOD)			return rc;		rc = usbat_device_enable_cdt(us);		if (rc != USB_STOR_TRANSPORT_GOOD)			return rc;		msleep(50);		rc = usbat_read_user_io(us, uio);		if (rc != USB_STOR_XFER_GOOD)			return USB_STOR_TRANSPORT_ERROR;				info->sense_key = UNIT_ATTENTION;		info->sense_asc = 0x28;		info->sense_ascq = 0x00;		return USB_STOR_TRANSPORT_FAILED;	}	return USB_STOR_TRANSPORT_GOOD;}/* * Determine whether we are controlling a flash-based reader/writer, * or a HP8200-based CD drive. * Sets transport functions as appropriate. */static int usbat_identify_device(struct us_data *us,				 struct usbat_info *info){	int rc;	unsigned char status;	if (!us || !info)		return USB_STOR_TRANSPORT_ERROR;	rc = usbat_device_reset(us);	if (rc != USB_STOR_TRANSPORT_GOOD)		return rc;	msleep(500);	/*	 * In attempt to distinguish between HP CDRW's and Flash readers, we now	 * execute the IDENTIFY PACKET DEVICE command. On ATA devices (i.e. flash	 * readers), this command should fail with error. On ATAPI devices (i.e.	 * CDROM drives), it should succeed.	 */	rc = usbat_write(us, USBAT_ATA, USBAT_ATA_CMD, 0xA1); 	if (rc != USB_STOR_XFER_GOOD) 		return USB_STOR_TRANSPORT_ERROR;	rc = usbat_get_status(us, &status); 	if (rc != USB_STOR_XFER_GOOD) 		return USB_STOR_TRANSPORT_ERROR;	/* Check for error bit, or if the command 'fell through' */	if (status == 0xA1 || !(status & 0x01)) {		/* Device is HP 8200 */		US_DEBUGP("usbat_identify_device: Detected HP8200 CDRW\n");		info->devicetype = USBAT_DEV_HP8200;	} else {		/* Device is a CompactFlash reader/writer */		US_DEBUGP("usbat_identify_device: Detected Flash reader/writer\n");		info->devicetype = USBAT_DEV_FLASH;	}	return USB_STOR_TRANSPORT_GOOD;}/* * Set the transport function based on the device type */static int usbat_set_transport(struct us_data *us,			       struct usbat_info *info){	int rc;	if (!info->devicetype) {		rc = usbat_identify_device(us, info);		if (rc != USB_STOR_TRANSPORT_GOOD) {			US_DEBUGP("usbat_set_transport: Could not identify device\n");			return 1;		}	}	if (usbat_get_device_type(us) == USBAT_DEV_HP8200)		us->transport = usbat_hp8200e_transport;	else if (usbat_get_device_type(us) == USBAT_DEV_FLASH)		us->transport = usbat_flash_transport;	return 0;}/* * Read the media capacity */static int usbat_flash_get_sector_count(struct us_data *us,					struct usbat_info *info){	unsigned char registers[3] = {		USBAT_ATA_SECCNT,		USBAT_ATA_DEVICE,		USBAT_ATA_CMD,	};	unsigned char  command[3] = { 0x01, 0xA0, 0xEC };	unsigned char *reply;	unsigned char status;	int rc;	if (!us || !info)		return USB_STOR_TRANSPORT_ERROR;	reply = kmalloc(512, GFP_NOIO);	if (!reply)		return USB_STOR_TRANSPORT_ERROR;	/* ATA command : IDENTIFY DEVICE */	rc = usbat_multiple_write(us, registers, command, 3);	if (rc != USB_STOR_XFER_GOOD) {		US_DEBUGP("usbat_flash_get_sector_count: Gah! identify_device failed\n");		rc = USB_STOR_TRANSPORT_ERROR;		goto leave;	}	/* Read device status */	if (usbat_get_status(us, &status) != USB_STOR_XFER_GOOD) {		rc = USB_STOR_TRANSPORT_ERROR;		goto leave;	}	msleep(100);	/* Read the device identification data */	rc = usbat_read_block(us, reply, 512);	if (rc != USB_STOR_TRANSPORT_GOOD)		goto leave;	info->sectors = ((u32)(reply[117]) << 24) |		((u32)(reply[116]) << 16) |		((u32)(reply[115]) <<  8) |		((u32)(reply[114])      );	rc = USB_STOR_TRANSPORT_GOOD; leave:	kfree(reply);	return rc;}/* * Read data from device */static int usbat_flash_read_data(struct us_data *us,								 struct usbat_info *info,								 u32 sector,								 u32 sectors){	unsigned char registers[7] = {		USBAT_ATA_FEATURES,		USBAT_ATA_SECCNT,		USBAT_ATA_SECNUM,		USBAT_ATA_LBA_ME,		USBAT_ATA_LBA_HI,		USBAT_ATA_DEVICE,		USBAT_ATA_STATUS,	};	unsigned char command[7];	unsigned char *buffer;	unsigned char  thistime;	unsigned int totallen, alloclen;	int len, result;	unsigned int sg_idx = 0, sg_offset = 0;	result = usbat_flash_check_media(us, info);	if (result != USB_STOR_TRANSPORT_GOOD)		return result;	/*	 * we're working in LBA mode.  according to the ATA spec,	 * we can support up to 28-bit addressing.  I don't know if Jumpshot	 * supports beyond 24-bit addressing.  It's kind of hard to test	 * since it requires > 8GB CF card.	 */	if (sector > 0x0FFFFFFF)		return USB_STOR_TRANSPORT_ERROR;	totallen = sectors * info->ssize;	/*	 * Since we don't read more than 64 KB at a time, we have to create	 * a bounce buffer and move the data a piece at a time between the	 * bounce buffer and the actual transfer buffer.	 */	alloclen = min(totallen, 65536u);	buffer = kmalloc(alloclen, GFP_NOIO);	if (buffer == NULL)		return USB_STOR_TRANSPORT_ERROR;	do {		/*		 * loop, never allocate or transfer more than 64k at once		 * (min(128k, 255*info->ssize) is the real limit)		 */		len = min(totallen, alloclen);		thistime = (len / info->ssize) & 0xff; 		/* ATA command 0x20 (READ SECTORS) */		usbat_pack_ata_sector_cmd(command, thistime, sector, 0x20);		/* Write/execute ATA read command */		result = usbat_multiple_write(us, registers, command, 7);		if (result != USB_STOR_TRANSPORT_GOOD)			goto leave;		/* Read the data we just requested */		result = usbat_read_blocks(us, buffer, len);		if (result != USB_STOR_TRANSPORT_GOOD)			goto leave;  	 		US_DEBUGP("usbat_flash_read_data:  %d bytes\n", len);			/* Store the data in the transfer buffer */		usb_stor_access_xfer_buf(buffer, len, us->srb,					 &sg_idx, &sg_offset, TO_XFER_BUF);		sector += thistime;		totallen -= len;	} while (totallen > 0);	kfree(buffer);	return USB_STOR_TRANSPORT_GOOD;leave:	kfree(buffer);	return USB_STOR_TRANSPORT_ERROR;}/* * Write data to device */static int usbat_flash_write_data(struct us_data *us,								  struct usbat_info *info,								  u32 sector,								  u32 sectors){	unsigned char registers[7] = {		USBAT_ATA_FEATURES,		USBAT_ATA_SECCNT,		USBAT_ATA_SECNUM,		USBAT_ATA_LBA_ME,		USBAT_ATA_LBA_HI,		USBAT_ATA_DEVICE,		USBAT_ATA_STATUS,	};	unsigned char command[7];	unsigned char *buffer;	unsigned char  thistime;	unsigned int totallen, alloclen;	int len, result;	unsigned int sg_idx = 0, sg_offset = 0;	result = usbat_flash_check_media(us, info);	if (result != USB_STOR_TRANSPORT_GOOD)		return result;	/*	 * we're working in LBA mode.  according to the ATA spec,	 * we can support up to 28-bit addressing.  I don't know if the device	 * supports beyond 24-bit addressing.  It's kind of hard to test	 * since it requires > 8GB media.	 */	if (sector > 0x0FFFFFFF)		return USB_STOR_TRANSPORT_ERROR;	totallen = sectors * info->ssize;	/*	 * Since we don't write more than 64 KB at a time, we have to create	 * a bounce buffer and move the data a piece at a time between the	 * bounce buffer and the actual transfer buffer.	 */	alloclen = min(totallen, 65536u);	buffer = kmalloc(alloclen, GFP_NOIO);	if (buffer == NULL)		return USB_STOR_TRANSPORT_ERROR;	do {		/*		 * loop, never allocate or transfer more than 64k at once		 * (min(128k, 255*info->ssize) is the real limit)		 */		len = min(totallen, alloclen);		thistime = (len / info->ssize) & 0xff;		/* Get the data from the transfer buffer */		usb_stor_access_xfer_buf(buffer, len, us->srb,					 &sg_idx, &sg_offset, FROM_XFER_BUF);		/* ATA command 0x30 (WRITE SECTORS) */		usbat_pack_ata_sector_cmd(command, thistime, sector, 0x30);		/* Write/execute ATA write command */		result = usbat_multiple_write(us, registers, command, 7);		if (result != USB_STOR_TRANSPORT_GOOD)			goto leave;		/* Write the data */		result = usbat_write_blocks(us, buffer, len);		if (result != USB_STOR_TRANSPORT_GOOD)			goto leave;		sector += thistime;		totallen -= len;	} while (totallen > 0);	kfree(buffer);	return result;leave:	kfree(buffer);	return USB_STOR_TRANSPORT_ERROR;}/* * Squeeze a potentially huge (> 65535 byte) read10 command into * a little ( <= 65535 byte) ATAPI pipe

⌨️ 快捷键说明

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