linux/drivers/usb/storage/shuttle_usbat.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable
 *
 * Current development and maintenance by:
 *   (c) 2000, 2001 Robert Baruch ([email protected])
 *   (c) 2004, 2005 Daniel Drake <[email protected]>
 *
 * Developed with the assistance of:
 *   (c) 2002 Alan Stern <[email protected]>
 *
 * Flash support based on earlier work by:
 *   (c) 2002 Thomas Kreiling <[email protected]>
 *
 * 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.
 */

#include <linux/errno.h>
#include <linux/module.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 "scsiglue.h"

#define DRV_NAME

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();
MODULE_IMPORT_NS();

/* Supported device types */
#define USBAT_DEV_HP8200
#define USBAT_DEV_FLASH

#define USBAT_EPP_PORT
#define USBAT_EPP_REGISTER
#define USBAT_ATA
#define USBAT_ISA

/* Commands (need to be logically OR'd with an access type */
#define USBAT_CMD_READ_REG
#define USBAT_CMD_WRITE_REG
#define USBAT_CMD_READ_BLOCK
#define USBAT_CMD_WRITE_BLOCK
#define USBAT_CMD_COND_READ_BLOCK
#define USBAT_CMD_COND_WRITE_BLOCK
#define USBAT_CMD_WRITE_REGS

/* Commands (these don't need an access type) */
#define USBAT_CMD_EXEC_CMD
#define USBAT_CMD_SET_FEAT
#define USBAT_CMD_UIO

/* Methods of accessing UIO register */
#define USBAT_UIO_READ
#define USBAT_UIO_WRITE

/* Qualifier bits */
#define USBAT_QUAL_FCQ
#define USBAT_QUAL_ALQ

/* USBAT Flash Media status types */
#define USBAT_FLASH_MEDIA_NONE
#define USBAT_FLASH_MEDIA_CF

/* USBAT Flash Media change types */
#define USBAT_FLASH_MEDIA_SAME
#define USBAT_FLASH_MEDIA_CHANGED

/* USBAT ATA registers */
#define USBAT_ATA_DATA
#define USBAT_ATA_FEATURES
#define USBAT_ATA_ERROR
#define USBAT_ATA_SECCNT
#define USBAT_ATA_SECNUM
#define USBAT_ATA_LBA_ME
#define USBAT_ATA_LBA_HI
#define USBAT_ATA_DEVICE
#define USBAT_ATA_STATUS
#define USBAT_ATA_CMD
#define USBAT_ATA_ALTSTATUS

/* USBAT User I/O Data registers */
#define USBAT_UIO_EPAD
#define USBAT_UIO_CDT
				     /* CDT = ACKD & !UI1 & !UI0 */
#define USBAT_UIO_1
#define USBAT_UIO_0
#define USBAT_UIO_EPP_ATA
#define USBAT_UIO_UI1
#define USBAT_UIO_UI0
#define USBAT_UIO_INTR_ACK

/* USBAT User I/O Enable registers */
#define USBAT_UIO_DRVRST
#define USBAT_UIO_ACKD
#define USBAT_UIO_OE1
				     /* If ACKD=1, set OE1 to 1 also. */
#define USBAT_UIO_OE0
#define USBAT_UIO_ADPRST

/* USBAT Features */
#define USBAT_FEAT_ETEN
#define USBAT_FEAT_U1
#define USBAT_FEAT_U0
#define USBAT_FEAT_ET1
#define USBAT_FEAT_ET2

struct usbat_info {};

#define short_pack(LSB,MSB)
#define LSB_of(s)
#define MSB_of(s)

static int transferred =;

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);

static int init_usbat_cd(struct us_data *us);
static int init_usbat_flash(struct us_data *us);


/*
 * The table of devices
 */
#define UNUSUAL_DEV

static struct usb_device_id usbat_usb_ids[] =;
MODULE_DEVICE_TABLE(usb, usbat_usb_ids);

#undef UNUSUAL_DEV

/*
 * The flags table
 */
#define UNUSUAL_DEV

static struct us_unusual_dev usbat_unusual_dev_list[] =;

#undef UNUSUAL_DEV

/*
 * 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)
{}

/*
 * Convenience function to get the device type (flash or hp8200)
 */
static int usbat_get_device_type(struct us_data *us)
{}

/*
 * Read a register from the device
 */
static int usbat_read(struct us_data *us,
		      unsigned char access,
		      unsigned char reg,
		      unsigned char *content)
{}

/*
 * Write to a register on the device
 */
static int usbat_write(struct us_data *us,
		       unsigned char access,
		       unsigned char reg,
		       unsigned char content)
{}

/*
 * Convenience function to perform a bulk read
 */
static int usbat_bulk_read(struct us_data *us,
			   void* buf,
			   unsigned int len,
			   int use_sg)
{}

/*
 * Convenience function to perform a bulk write
 */
static int usbat_bulk_write(struct us_data *us,
			    void* buf,
			    unsigned int len,
			    int use_sg)
{}

/*
 * 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)
{}

/*
 * Read the status register
 */
static int usbat_get_status(struct us_data *us, unsigned char *status)
{}

/*
 * Check the device status
 */
static int usbat_check_status(struct us_data *us)
{}

/*
 * Stores critical information in internal registers in preparation 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)
{}

/*
 * 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)
{}

/*
 * Read block data from the data register
 */
static int usbat_read_block(struct us_data *us,
			    void* buf,
			    unsigned short len,
			    int use_sg)
{}

/*
 * Write block data via the data register
 */
static int usbat_write_block(struct us_data *us,
			     unsigned char access,
			     void* buf,
			     unsigned short len,
			     int minutes,
			     int use_sg)
{}

/*
 * 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,
				       void *buf,
				       unsigned short len,
				       int use_sg,
				       int minutes)
{}

/*
 * 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)
{}

/*
 * 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,
			     void* buffer,
			     int len,
			     int use_sg)
{}

/*
 * 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,
			      void* buffer,
			      int len,
			      int use_sg)
{}

/*
 * Read the User IO register
 */
static int usbat_read_user_io(struct us_data *us, unsigned char *data_flags)
{}

/*
 * Write to the User IO register
 */
static int usbat_write_user_io(struct us_data *us,
			       unsigned char enable_flags,
			       unsigned char data_flags)
{}

/*
 * Reset the device
 * Often needed on media change.
 */
static int usbat_device_reset(struct us_data *us)
{}

/*
 * Enable card detect
 */
static int usbat_device_enable_cdt(struct us_data *us)
{}

/*
 * Determine if media is present.
 */
static int usbat_flash_check_media_present(struct us_data *us,
					   unsigned char *uio)
{}

/*
 * Determine if media has changed since last operation
 */
static int usbat_flash_check_media_changed(struct us_data *us,
					   unsigned char *uio)
{}

/*
 * 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)
{}

/*
 * 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)
{}

/*
 * Set the transport function based on the device type
 */
static int usbat_set_transport(struct us_data *us,
			       struct usbat_info *info,
			       int devicetype)
{}

/*
 * Read the media capacity
 */
static int usbat_flash_get_sector_count(struct us_data *us,
					struct usbat_info *info)
{}

/*
 * Read data from device
 */
static int usbat_flash_read_data(struct us_data *us,
								 struct usbat_info *info,
								 u32 sector,
								 u32 sectors)
{}

/*
 * Write data to device
 */
static int usbat_flash_write_data(struct us_data *us,
								  struct usbat_info *info,
								  u32 sector,
								  u32 sectors)
{}

/*
 * Squeeze a potentially huge (> 65535 byte) read10 command into
 * a little ( <= 65535 byte) ATAPI pipe
 */
static int usbat_hp8200e_handle_read10(struct us_data *us,
				       unsigned char *registers,
				       unsigned char *data,
				       struct scsi_cmnd *srb)
{}

static int usbat_select_and_test_registers(struct us_data *us)
{}

/*
 * Initialize the USBAT processor and the storage device
 */
static int init_usbat(struct us_data *us, int devicetype)
{}

/*
 * Transport for the HP 8200e
 */
static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
{}

/*
 * Transport for USBAT02-based CompactFlash and similar storage devices
 */
static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
{}

static int init_usbat_cd(struct us_data *us)
{}

static int init_usbat_flash(struct us_data *us)
{}

static struct scsi_host_template usbat_host_template;

static int usbat_probe(struct usb_interface *intf,
			 const struct usb_device_id *id)
{}

static struct usb_driver usbat_driver =;

module_usb_stor_driver(usbat_driver, usbat_host_template, DRV_NAME);