// 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 (bjorn@haxx.se)
*
* Developed with the assistance of:
* (C) 2002 Alan Stern <stern@rowland.org>
*
* Initial work:
* (C) 2000 In-System Design, Inc. (support@in-system.com)
*
* 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 <stern@rowland.harvard.edu>)
* 2001-02-24: Removed lots of duplicate code and simplified the structure.
* (bjorn@haxx.se)
* 2002-01-16: Fixed endianness bug so it works on the ppc arch.
* (Luc Saillard <luc@saillard.org>)
* 2002-01-17: All bitfields removed.
* (bjorn@haxx.se)
*/
/* 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 "ums-isd200"
MODULE_DESCRIPTION("Driver for In-System Design, Inc. ISD200 ASIC");
MODULE_AUTHOR("Björn Stenberg <bjorn@haxx.se>");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS("USB_STORAGE");
static int isd200_Initialization(struct us_data *us);
/*
* The table of devices
*/
#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
vendorName, productName, useProtocol, useTransport, \
initFunction, flags) \
{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
.driver_info = (flags) }
static const struct usb_device_id isd200_usb_ids[] = {
# include "unusual_isd200.h"
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, isd200_usb_ids);
#undef UNUSUAL_DEV
/*
* The flags table
*/
#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
vendor_name, product_name, use_protocol, use_transport, \
init_function, Flags) \
{ \
.vendorName = vendor_name, \
.productName = product_name, \
.useProtocol = use_protocol, \
.useTransport = use_transport, \
.initFunction = init_function, \
}
static const struct us_unusual_dev isd200_unusual_dev_list[] = {
# include "unusual_isd200.h"
{ } /* Terminating entry */
};
#undef UNUSUAL_DEV
/* Timeout defines (in Seconds) */
#define ISD200_ENUM_BSY_TIMEOUT 35
#define ISD200_ENUM_DETECT_TIMEOUT 30
#define ISD200_DEFAULT_TIMEOUT 30
/* device flags */
#define DF_ATA_DEVICE 0x0001
#define DF_MEDIA_STATUS_ENABLED 0x0002
#define DF_REMOVABLE_MEDIA 0x0004
/* capability bit definitions */
#define CAPABILITY_DMA 0x01
#define CAPABILITY_LBA 0x02
/* command_setX bit definitions */
#define COMMANDSET_REMOVABLE 0x02
#define COMMANDSET_MEDIA_STATUS 0x10
/* ATA Vendor Specific defines */
#define ATA_ADDRESS_DEVHEAD_STD 0xa0
#define ATA_ADDRESS_DEVHEAD_LBA_MODE 0x40
#define ATA_ADDRESS_DEVHEAD_SLAVE 0x10
/* Action Select bits */
#define ACTION_SELECT_0 0x01
#define ACTION_SELECT_1 0x02
#define ACTION_SELECT_2 0x04
#define ACTION_SELECT_3 0x08
#define ACTION_SELECT_4 0x10
#define ACTION_SELECT_5 0x20
#define ACTION_SELECT_6 0x40
#define ACTION_SELECT_7 0x80
/* Register Select bits */
#define REG_ALTERNATE_STATUS 0x01
#define REG_DEVICE_CONTROL 0x01
#define REG_ERROR 0x02
#define REG_FEATURES 0x02
#define REG_SECTOR_COUNT 0x04
#define REG_SECTOR_NUMBER 0x08
#define REG_CYLINDER_LOW 0x10
#define REG_CYLINDER_HIGH 0x20
#define REG_DEVICE_HEAD 0x40
#define REG_STATUS 0x80
#define REG_COMMAND 0x80
/* ATA registers offset definitions */
#define ATA_REG_ERROR_OFFSET 1
#define ATA_REG_LCYL_OFFSET 4
#define ATA_REG_HCYL_OFFSET 5
#define ATA_REG_STATUS_OFFSET 7
/* ATA error definitions not in <linux/hdreg.h> */
#define ATA_ERROR_MEDIA_CHANGE 0x20
/* ATA command definitions not in <linux/hdreg.h> */
#define ATA_COMMAND_GET_MEDIA_STATUS 0xDA
#define ATA_COMMAND_MEDIA_EJECT 0xED
/* ATA drive control definitions */
#define ATA_DC_DISABLE_INTERRUPTS 0x02
#define ATA_DC_RESET_CONTROLLER 0x04
#define ATA_DC_REENABLE_CONTROLLER 0x00
/*
* General purpose return codes
*/
#define ISD200_ERROR -1
#define ISD200_GOOD 0
/*
* Transport return codes
*/
#define ISD200_TRANSPORT_GOOD 0 /* Transport good, command good */
#define ISD200_TRANSPORT_FAILED 1 /* Transport good, command failed */
#define ISD200_TRANSPORT_ERROR 2 /* Transport bad (i.e. device dead) */
/* driver action codes */
#define ACTION_READ_STATUS 0
#define ACTION_RESET 1
#define ACTION_REENABLE 2
#define ACTION_SOFT_RESET 3
#define ACTION_ENUM 4
#define ACTION_IDENTIFY 5
/*
* ata_cdb struct
*/
union ata_cdb {
struct {
unsigned char SignatureByte0;
unsigned char SignatureByte1;
unsigned char ActionSelect;
unsigned char RegisterSelect;
unsigned char TransferBlockSize;
unsigned char WriteData3F6;
unsigned char WriteData1F1;
unsigned char WriteData1F2;
unsigned char WriteData1F3;
unsigned char WriteData1F4;
unsigned char WriteData1F5;
unsigned char WriteData1F6;
unsigned char WriteData1F7;
unsigned char Reserved[3];
} generic;
struct {
unsigned char SignatureByte0;
unsigned char SignatureByte1;
unsigned char ActionSelect;
unsigned char RegisterSelect;
unsigned char TransferBlockSize;
unsigned char AlternateStatusByte;
unsigned char ErrorByte;
unsigned char SectorCoun
|