// SPDX-License-Identifier: GPL-2.0+ /* * Transport & Protocol Driver for In-System Design, Inc. ISD200 ASIC * * Current development and maintenance: * (C) 2001-2002 Björn Stenberg ([email protected]) * * Developed with the assistance of: * (C) 2002 Alan Stern <[email protected]> * * Initial work: * (C) 2000 In-System Design, Inc. ([email protected]) * * The ISD200 ASIC does not natively support ATA devices. The chip * does implement an interface, the ATA Command Block (ATACB) which provides * a means of passing ATA commands and ATA register accesses to a device. * * History: * * 2002-10-19: Removed the specialized transfer routines. * (Alan Stern <[email protected]>) * 2001-02-24: Removed lots of duplicate code and simplified the structure. * ([email protected]) * 2002-01-16: Fixed endianness bug so it works on the ppc arch. * (Luc Saillard <[email protected]>) * 2002-01-17: All bitfields removed. * ([email protected]) */ /* Include files */ #include <linux/jiffies.h> #include <linux/errno.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/ata.h> #include <linux/hdreg.h> #include <linux/scatterlist.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.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(…); static int isd200_Initialization(struct us_data *us); /* * The table of devices */ #define UNUSUAL_DEV … static struct usb_device_id isd200_usb_ids[] = …; MODULE_DEVICE_TABLE(usb, isd200_usb_ids); #undef UNUSUAL_DEV /* * The flags table */ #define UNUSUAL_DEV … static struct us_unusual_dev isd200_unusual_dev_list[] = …; #undef UNUSUAL_DEV /* Timeout defines (in Seconds) */ #define ISD200_ENUM_BSY_TIMEOUT … #define ISD200_ENUM_DETECT_TIMEOUT … #define ISD200_DEFAULT_TIMEOUT … /* device flags */ #define DF_ATA_DEVICE … #define DF_MEDIA_STATUS_ENABLED … #define DF_REMOVABLE_MEDIA … /* capability bit definitions */ #define CAPABILITY_DMA … #define CAPABILITY_LBA … /* command_setX bit definitions */ #define COMMANDSET_REMOVABLE … #define COMMANDSET_MEDIA_STATUS … /* ATA Vendor Specific defines */ #define ATA_ADDRESS_DEVHEAD_STD … #define ATA_ADDRESS_DEVHEAD_LBA_MODE … #define ATA_ADDRESS_DEVHEAD_SLAVE … /* Action Select bits */ #define ACTION_SELECT_0 … #define ACTION_SELECT_1 … #define ACTION_SELECT_2 … #define ACTION_SELECT_3 … #define ACTION_SELECT_4 … #define ACTION_SELECT_5 … #define ACTION_SELECT_6 … #define ACTION_SELECT_7 … /* Register Select bits */ #define REG_ALTERNATE_STATUS … #define REG_DEVICE_CONTROL … #define REG_ERROR … #define REG_FEATURES … #define REG_SECTOR_COUNT … #define REG_SECTOR_NUMBER … #define REG_CYLINDER_LOW … #define REG_CYLINDER_HIGH … #define REG_DEVICE_HEAD … #define REG_STATUS … #define REG_COMMAND … /* ATA registers offset definitions */ #define ATA_REG_ERROR_OFFSET … #define ATA_REG_LCYL_OFFSET … #define ATA_REG_HCYL_OFFSET … #define ATA_REG_STATUS_OFFSET … /* ATA error definitions not in <linux/hdreg.h> */ #define ATA_ERROR_MEDIA_CHANGE … /* ATA command definitions not in <linux/hdreg.h> */ #define ATA_COMMAND_GET_MEDIA_STATUS … #define ATA_COMMAND_MEDIA_EJECT … /* ATA drive control definitions */ #define ATA_DC_DISABLE_INTERRUPTS … #define ATA_DC_RESET_CONTROLLER … #define ATA_DC_REENABLE_CONTROLLER … /* * General purpose return codes */ #define ISD200_ERROR … #define ISD200_GOOD … /* * Transport return codes */ #define ISD200_TRANSPORT_GOOD … #define ISD200_TRANSPORT_FAILED … #define ISD200_TRANSPORT_ERROR … /* driver action codes */ #define ACTION_READ_STATUS … #define ACTION_RESET … #define ACTION_REENABLE … #define ACTION_SOFT_RESET … #define ACTION_ENUM … #define ACTION_IDENTIFY … /* * ata_cdb struct */ ata_cdb; /* * Inquiry data structure. This is the data returned from the target * after it receives an inquiry. * * This structure may be extended by the number of bytes specified * in the field AdditionalLength. The defined size constant only * includes fields through ProductRevisionLevel. */ /* * DeviceType field */ #define DIRECT_ACCESS_DEVICE … #define DEVICE_REMOVABLE … struct inquiry_data { … } __attribute__ ((packed)); /* * INQUIRY data buffer size */ #define INQUIRYDATABUFFERSIZE … /* * ISD200 CONFIG data struct */ #define ATACFG_TIMING … #define ATACFG_ATAPI_RESET … #define ATACFG_MASTER … #define ATACFG_BLOCKSIZE … #define ATACFGE_LAST_LUN … #define ATACFGE_DESC_OVERRIDE … #define ATACFGE_STATE_SUSPEND … #define ATACFGE_SKIP_BOOT … #define ATACFGE_CONF_DESC2 … #define ATACFGE_INIT_STATUS … #define CFG_CAPABILITY_SRST … struct isd200_config { … }__attribute__ ((packed)); /* * ISD200 driver information struct */ struct isd200_info { … }; /* * Read Capacity Data - returned in Big Endian format */ struct read_capacity_data { … }; /* * Read Block Limits Data - returned in Big Endian format * This structure returns the maximum and minimum block * size for a TAPE device. */ struct read_block_limits { … }; /* * Sense Data Format */ #define SENSE_ERRCODE … #define SENSE_ERRCODE_VALID … #define SENSE_FLAG_SENSE_KEY … #define SENSE_FLAG_BAD_LENGTH … #define SENSE_FLAG_END_OF_MEDIA … #define SENSE_FLAG_FILE_MARK … struct sense_data { … } __attribute__ ((packed)); /* * Default request sense buffer size */ #define SENSE_BUFFER_SIZE … /*********************************************************************** * Helper routines ***********************************************************************/ /************************************************************************** * isd200_build_sense * * Builds an artificial sense buffer to report the results of a * failed command. * * RETURNS: * void */ static void isd200_build_sense(struct us_data *us, struct scsi_cmnd *srb) { … } /*********************************************************************** * Transport routines ***********************************************************************/ /************************************************************************** * isd200_set_srb(), isd200_srb_set_bufflen() * * Two helpers to facilitate in initialization of scsi_cmnd structure * Will need to change when struct scsi_cmnd changes */ static void isd200_set_srb(struct isd200_info *info, enum dma_data_direction dir, void* buff, unsigned bufflen) { … } static void isd200_srb_set_bufflen(struct scsi_cmnd *srb, unsigned bufflen) { … } /************************************************************************** * isd200_action * * Routine for sending commands to the isd200 * * RETURNS: * ISD status code */ static int isd200_action( struct us_data *us, int action, void* pointer, int value ) { … } /************************************************************************** * isd200_read_regs * * Read ATA Registers * * RETURNS: * ISD status code */ static int isd200_read_regs( struct us_data *us ) { … } /************************************************************************** * Invoke the transport and basic error-handling/recovery methods * * This is used by the protocol layers to actually send the message to * the device and receive the response. */ static void isd200_invoke_transport( struct us_data *us, struct scsi_cmnd *srb, union ata_cdb *ataCdb ) { … } #ifdef CONFIG_USB_STORAGE_DEBUG static void isd200_log_config(struct us_data *us, struct isd200_info *info) { … } #endif /************************************************************************** * isd200_write_config * * Write the ISD200 Configuration data * * RETURNS: * ISD status code */ static int isd200_write_config( struct us_data *us ) { … } /************************************************************************** * isd200_read_config * * Reads the ISD200 Configuration data * * RETURNS: * ISD status code */ static int isd200_read_config( struct us_data *us ) { … } /************************************************************************** * isd200_atapi_soft_reset * * Perform an Atapi Soft Reset on the device * * RETURNS: * NT status code */ static int isd200_atapi_soft_reset( struct us_data *us ) { … } /************************************************************************** * isd200_srst * * Perform an SRST on the device * * RETURNS: * ISD status code */ static int isd200_srst( struct us_data *us ) { … } /************************************************************************** * isd200_try_enum * * Helper function for isd200_manual_enum(). Does ENUM and READ_STATUS * and tries to analyze the status registers * * RETURNS: * ISD status code */ static int isd200_try_enum(struct us_data *us, unsigned char master_slave, int detect ) { … } /************************************************************************** * isd200_manual_enum * * Determines if the drive attached is an ATA or ATAPI and if it is a * master or slave. * * RETURNS: * ISD status code */ static int isd200_manual_enum(struct us_data *us) { … } static void isd200_fix_driveid(u16 *id) { … } static void isd200_dump_driveid(struct us_data *us, u16 *id) { … } /************************************************************************** * isd200_get_inquiry_data * * Get inquiry data * * RETURNS: * ISD status code */ static int isd200_get_inquiry_data( struct us_data *us ) { … } /************************************************************************** * isd200_scsi_to_ata * * Translate SCSI commands to ATA commands. * * RETURNS: * 1 if the command needs to be sent to the transport layer * 0 otherwise */ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us, union ata_cdb * ataCdb) { … } /************************************************************************** * isd200_free_info * * Frees the driver structure. */ static void isd200_free_info_ptrs(void *info_) { … } /************************************************************************** * isd200_init_info * * Allocates (if necessary) and initializes the driver structure. * * RETURNS: * error status code */ static int isd200_init_info(struct us_data *us) { … } /************************************************************************** * Initialization for the ISD200 */ static int isd200_Initialization(struct us_data *us) { … } /************************************************************************** * 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 connected as a slave device will be * detected in the driver initialization function and the protocol will * be changed to an ATAPI protocol (Transparent SCSI). * */ static void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) { … } static struct scsi_host_template isd200_host_template; static int isd200_probe(struct usb_interface *intf, const struct usb_device_id *id) { … } static struct usb_driver isd200_driver = …; module_usb_stor_driver(isd200_driver, isd200_host_template, DRV_NAME);