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

📄 shuttle_usbat.c

📁 usb 子设备程序 支持sd卡 mouse keyboard 的最单单的驱动程序 gcc编译 支持
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable * * $Id: shuttle_usbat.c,v 1.1.1.1 2007/06/12 07:27:09 eyryu Exp $ * * Current development and maintenance by: *   (c) 2000, 2001 Robert Baruch (autophile@starband.net) *   (c) 2004, 2005 Daniel Drake <dsd@gentoo.org> * * Developed with the assistance of: *   (c) 2002 Alan Stern <stern@rowland.org> * * Flash support based on earlier work by: *   (c) 2002 Thomas Kreiling <usbdev@sm04.de> * * Many originally ATAPI devices were slightly modified to meet the USB * market by using some kind of translation from ATAPI to USB on the host, * and the peripheral would translate from USB back to ATAPI. * * SCM Microsystems (www.scmmicro.com) makes a device, sold to OEM's only,  * which does the USB-to-ATAPI conversion.  By obtaining the data sheet on * their device under nondisclosure agreement, I have been able to write * this driver for Linux. * * The chip used in the device can also be used for EPP and ISA translation * as well. This driver is only guaranteed to work with the ATAPI * translation. * * See the Kconfig help text for a list of devices known to be supported by * this driver. * * 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. */#include <linux/errno.h>#include <linux/slab.h>#include <linux/cdrom.h>#include <scsi/scsi.h>#include <scsi/scsi_cmnd.h>#include "usb.h"#include "transport.h"#include "protocol.h"#include "debug.h"#include "shuttle_usbat.h"#define short_pack(LSB,MSB) ( ((u16)(LSB)) | ( ((u16)(MSB))<<8 ) )#define LSB_of(s) ((s)&0xFF)#define MSB_of(s) ((s)>>8)static int transferred = 0;static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us);static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us);/* * Convenience function to produce an ATA read/write sectors command * Use cmd=0x20 for read, cmd=0x30 for write */static void usbat_pack_ata_sector_cmd(unsigned char *buf,					unsigned char thistime,					u32 sector, unsigned char cmd){	buf[0] = 0;	buf[1] = thistime;	buf[2] = sector & 0xFF;	buf[3] = (sector >>  8) & 0xFF;	buf[4] = (sector >> 16) & 0xFF;	buf[5] = 0xE0 | ((sector >> 24) & 0x0F);	buf[6] = cmd;}/* * Convenience function to get the device type (flash or hp8200) */static int usbat_get_device_type(struct us_data *us){	return ((struct usbat_info*)us->extra)->devicetype;}/* * Read a register from the device */static int usbat_read(struct us_data *us,		      unsigned char access,		      unsigned char reg,		      unsigned char *content){	return usb_stor_ctrl_transfer(us,		us->recv_ctrl_pipe,		access | USBAT_CMD_READ_REG,		0xC0,		(u16)reg,		0,		content,		1);}/* * Write to a register on the device */static int usbat_write(struct us_data *us,		       unsigned char access,		       unsigned char reg,		       unsigned char content){	return usb_stor_ctrl_transfer(us,		us->send_ctrl_pipe,		access | USBAT_CMD_WRITE_REG,		0x40,		short_pack(reg, content),		0,		NULL,		0);}/* * Convenience function to perform a bulk read */static int usbat_bulk_read(struct us_data *us,			   unsigned char *data,			   unsigned int len,			   int use_sg){	if (len == 0)		return USB_STOR_XFER_GOOD;	US_DEBUGP("usbat_bulk_read: len = %d\n", len);	return usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe, data, len, use_sg, NULL);}/* * Convenience function to perform a bulk write */static int usbat_bulk_write(struct us_data *us,			    unsigned char *data,			    unsigned int len,			    int use_sg){	if (len == 0)		return USB_STOR_XFER_GOOD;	US_DEBUGP("usbat_bulk_write:  len = %d\n", len);	return usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe, data, len, use_sg, NULL);}/* * Some USBAT-specific commands can only be executed over a command transport * This transport allows one (len=8) or two (len=16) vendor-specific commands * to be executed. */static int usbat_execute_command(struct us_data *us,								 unsigned char *commands,								 unsigned int len){	return usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,								  USBAT_CMD_EXEC_CMD, 0x40, 0, 0,								  commands, len);}/* * Read the status register */static int usbat_get_status(struct us_data *us, unsigned char *status){	int rc;	rc = usbat_read(us, USBAT_ATA, USBAT_ATA_STATUS, status);	US_DEBUGP("usbat_get_status: 0x%02X\n", (unsigned short) (*status));	return rc;}/* * Check the device status */static int usbat_check_status(struct us_data *us){	unsigned char *reply = us->iobuf;	int rc;	if (!us)		return USB_STOR_TRANSPORT_ERROR;	rc = usbat_get_status(us, reply);	if (rc != USB_STOR_XFER_GOOD)		return USB_STOR_TRANSPORT_FAILED;	/* error/check condition (0x51 is ok) */	if (*reply & 0x01 && *reply != 0x51)		return USB_STOR_TRANSPORT_FAILED;	/* device fault */	if (*reply & 0x20)		return USB_STOR_TRANSPORT_FAILED;	return USB_STOR_TRANSPORT_GOOD;}/* * Stores critical information in internal registers in prepartion for the execution * of a conditional usbat_read_blocks or usbat_write_blocks call. */static int usbat_set_shuttle_features(struct us_data *us,				      unsigned char external_trigger,				      unsigned char epp_control,				      unsigned char mask_byte,				      unsigned char test_pattern,				      unsigned char subcountH,				      unsigned char subcountL){	unsigned char *command = us->iobuf;	command[0] = 0x40;	command[1] = USBAT_CMD_SET_FEAT;	/*	 * The only bit relevant to ATA access is bit 6	 * which defines 8 bit data access (set) or 16 bit (unset)	 */	command[2] = epp_control;	/*	 * If FCQ is set in the qualifier (defined in R/W cmd), then bits U0, U1,	 * ET1 and ET2 define an external event to be checked for on event of a	 * _read_blocks or _write_blocks operation. The read/write will not take	 * place unless the defined trigger signal is active.	 */	command[3] = external_trigger;	/*	 * The resultant byte of the mask operation (see mask_byte) is compared for	 * equivalence with this test pattern. If equal, the read/write will take	 * place.	 */	command[4] = test_pattern;	/*	 * This value is logically ANDed with the status register field specified	 * in the read/write command.	 */	command[5] = mask_byte;	/*	 * If ALQ is set in the qualifier, this field contains the address of the	 * registers where the byte count should be read for transferring the data.	 * If ALQ is not set, then this field contains the number of bytes to be	 * transferred.	 */	command[6] = subcountL;	command[7] = subcountH;	return usbat_execute_command(us, command, 8);}/* * Block, waiting for an ATA device to become not busy or to report * an error condition. */static int usbat_wait_not_busy(struct us_data *us, int minutes){	int i;	int result;	unsigned char *status = us->iobuf;	/* Synchronizing cache on a CDR could take a heck of a long time,	 * but probably not more than 10 minutes or so. On the other hand,	 * doing a full blank on a CDRW at speed 1 will take about 75	 * minutes!	 */	for (i=0; i<1200+minutes*60; i++) { 		result = usbat_get_status(us, status);		if (result!=USB_STOR_XFER_GOOD)			return USB_STOR_TRANSPORT_ERROR;		if (*status & 0x01) { /* check condition */			result = usbat_read(us, USBAT_ATA, 0x10, status);			return USB_STOR_TRANSPORT_FAILED;		}		if (*status & 0x20) /* device fault */			return USB_STOR_TRANSPORT_FAILED;		if ((*status & 0x80)==0x00) { /* not busy */			US_DEBUGP("Waited not busy for %d steps\n", i);			return USB_STOR_TRANSPORT_GOOD;		}		if (i<500)			msleep(10); /* 5 seconds */		else if (i<700)			msleep(50); /* 10 seconds */		else if (i<1200)			msleep(100); /* 50 seconds */		else			msleep(1000); /* X minutes */	}	US_DEBUGP("Waited not busy for %d minutes, timing out.\n",		minutes);	return USB_STOR_TRANSPORT_FAILED;}/* * Read block data from the data register */static int usbat_read_block(struct us_data *us,			    unsigned char *content,			    unsigned short len,			    int use_sg){	int result;	unsigned char *command = us->iobuf;	if (!len)		return USB_STOR_TRANSPORT_GOOD;	command[0] = 0xC0;	command[1] = USBAT_ATA | USBAT_CMD_READ_BLOCK;	command[2] = USBAT_ATA_DATA;	command[3] = 0;	command[4] = 0;	command[5] = 0;	command[6] = LSB_of(len);	command[7] = MSB_of(len);	result = usbat_execute_command(us, command, 8);	if (result != USB_STOR_XFER_GOOD)		return USB_STOR_TRANSPORT_ERROR;	result = usbat_bulk_read(us, content, len, use_sg);	return (result == USB_STOR_XFER_GOOD ?			USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);}/* * Write block data via the data register */static int usbat_write_block(struct us_data *us,			     unsigned char access,			     unsigned char *content,			     unsigned short len,			     int minutes,			     int use_sg){	int result;	unsigned char *command = us->iobuf;	if (!len)		return USB_STOR_TRANSPORT_GOOD;	command[0] = 0x40;	command[1] = access | USBAT_CMD_WRITE_BLOCK;	command[2] = USBAT_ATA_DATA;	command[3] = 0;	command[4] = 0;	command[5] = 0;	command[6] = LSB_of(len);	command[7] = MSB_of(len);	result = usbat_execute_command(us, command, 8);	if (result != USB_STOR_XFER_GOOD)		return USB_STOR_TRANSPORT_ERROR;	result = usbat_bulk_write(us, content, len, use_sg);	if (result != USB_STOR_XFER_GOOD)		return USB_STOR_TRANSPORT_ERROR;	return usbat_wait_not_busy(us, minutes);}/* * Process read and write requests */static int usbat_hp8200e_rw_block_test(struct us_data *us,				       unsigned char access,				       unsigned char *registers,				       unsigned char *data_out,				       unsigned short num_registers,				       unsigned char data_reg,				       unsigned char status_reg,				       unsigned char timeout,				       unsigned char qualifier,				       int direction,				       unsigned char *content,				       unsigned short len,				       int use_sg,				       int minutes){	int result;	unsigned int pipe = (direction == DMA_FROM_DEVICE) ?			us->recv_bulk_pipe : us->send_bulk_pipe;	unsigned char *command = us->iobuf;	int i, j;	int cmdlen;	unsigned char *data = us->iobuf;	unsigned char *status = us->iobuf;	BUG_ON(num_registers > US_IOBUF_SIZE/2);	for (i=0; i<20; i++) {		/*		 * The first time we send the full command, which consists		 * of downloading the SCSI command followed by downloading		 * the data via a write-and-test.  Any other time we only		 * send the command to download the data -- the SCSI command		 * is still 'active' in some sense in the device.		 * 		 * We're only going to try sending the data 10 times. After		 * that, we just return a failure.		 */		if (i==0) {			cmdlen = 16;			/*			 * Write to multiple registers			 * Not really sure the 0x07, 0x17, 0xfc, 0xe7 is			 * necessary here, but that's what came out of the			 * trace every single time.			 */			command[0] = 0x40;

⌨️ 快捷键说明

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