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

📄 shuttle_usbat.c

📁 usb 子设备程序 支持sd卡 mouse keyboard 的最单单的驱动程序 gcc编译 支持
💻 C
📖 第 1 页 / 共 4 页
字号:
			command[1] = access | USBAT_CMD_WRITE_REGS;			command[2] = 0x07;			command[3] = 0x17;			command[4] = 0xFC;			command[5] = 0xE7;			command[6] = LSB_of(num_registers*2);			command[7] = MSB_of(num_registers*2);		} else			cmdlen = 8;		/* Conditionally read or write blocks */		command[cmdlen-8] = (direction==DMA_TO_DEVICE ? 0x40 : 0xC0);		command[cmdlen-7] = access |				(direction==DMA_TO_DEVICE ?				 USBAT_CMD_COND_WRITE_BLOCK : USBAT_CMD_COND_READ_BLOCK);		command[cmdlen-6] = data_reg;		command[cmdlen-5] = status_reg;		command[cmdlen-4] = timeout;		command[cmdlen-3] = qualifier;		command[cmdlen-2] = LSB_of(len);		command[cmdlen-1] = MSB_of(len);		result = usbat_execute_command(us, command, cmdlen);		if (result != USB_STOR_XFER_GOOD)			return USB_STOR_TRANSPORT_ERROR;		if (i==0) {			for (j=0; j<num_registers; j++) {				data[j<<1] = registers[j];				data[1+(j<<1)] = data_out[j];			}			result = usbat_bulk_write(us, data, num_registers*2, 0);			if (result != USB_STOR_XFER_GOOD)				return USB_STOR_TRANSPORT_ERROR;		}		result = usb_stor_bulk_transfer_sg(us,			pipe, content, len, use_sg, NULL);		/*		 * If we get a stall on the bulk download, we'll retry		 * the bulk download -- but not the SCSI command because		 * in some sense the SCSI command is still 'active' and		 * waiting for the data. Don't ask me why this should be;		 * I'm only following what the Windoze driver did.		 *		 * Note that a stall for the test-and-read/write command means		 * that the test failed. In this case we're testing to make		 * sure that the device is error-free		 * (i.e. bit 0 -- CHK -- of status is 0). The most likely		 * hypothesis is that the USBAT chip somehow knows what		 * the device will accept, but doesn't give the device any		 * data until all data is received. Thus, the device would		 * still be waiting for the first byte of data if a stall		 * occurs, even if the stall implies that some data was		 * transferred.		 */		if (result == USB_STOR_XFER_SHORT ||				result == USB_STOR_XFER_STALLED) {			/*			 * If we're reading and we stalled, then clear			 * the bulk output pipe only the first time.			 */			if (direction==DMA_FROM_DEVICE && i==0) {				if (usb_stor_clear_halt(us,						us->send_bulk_pipe) < 0)					return USB_STOR_TRANSPORT_ERROR;			}			/*			 * Read status: is the device angry, or just busy?			 */ 			result = usbat_read(us, USBAT_ATA, 				direction==DMA_TO_DEVICE ?					USBAT_ATA_STATUS : USBAT_ATA_ALTSTATUS,				status);			if (result!=USB_STOR_XFER_GOOD)				return USB_STOR_TRANSPORT_ERROR;			if (*status & 0x01) /* check condition */				return USB_STOR_TRANSPORT_FAILED;			if (*status & 0x20) /* device fault */				return USB_STOR_TRANSPORT_FAILED;			US_DEBUGP("Redoing %s\n",			  direction==DMA_TO_DEVICE ? "write" : "read");		} else if (result != USB_STOR_XFER_GOOD)			return USB_STOR_TRANSPORT_ERROR;		else			return usbat_wait_not_busy(us, minutes);	}	US_DEBUGP("Bummer! %s bulk data 20 times failed.\n",		direction==DMA_TO_DEVICE ? "Writing" : "Reading");	return USB_STOR_TRANSPORT_FAILED;}/* * Write to multiple registers: * Allows us to write specific data to any registers. The data to be written * gets packed in this sequence: reg0, data0, reg1, data1, ..., regN, dataN * which gets sent through bulk out. * Not designed for large transfers of data! */static int usbat_multiple_write(struct us_data *us,				unsigned char *registers,				unsigned char *data_out,				unsigned short num_registers){	int i, result;	unsigned char *data = us->iobuf;	unsigned char *command = us->iobuf;	BUG_ON(num_registers > US_IOBUF_SIZE/2);	/* Write to multiple registers, ATA access */	command[0] = 0x40;	command[1] = USBAT_ATA | USBAT_CMD_WRITE_REGS;	/* No relevance */	command[2] = 0;	command[3] = 0;	command[4] = 0;	command[5] = 0;	/* Number of bytes to be transferred (incl. addresses and data) */	command[6] = LSB_of(num_registers*2);	command[7] = MSB_of(num_registers*2);	/* 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, 0);	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 use_sg){	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, use_sg);	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 use_sg){	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, use_sg);	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;

⌨️ 快捷键说明

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