summaryrefslogtreecommitdiff
path: root/drivers/usb/storage/isd200.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/storage/isd200.c')
-rw-r--r--drivers/usb/storage/isd200.c154
1 files changed, 84 insertions, 70 deletions
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index 599d8bff26c3..a1669c35bad5 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -1,4 +1,6 @@
-/* Transport & Protocol Driver for In-System Design, Inc. ISD200 ASIC
+// 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)
@@ -13,20 +15,6 @@
* does implement an interface, the ATA Command Block (ATACB) which provides
* a means of passing ATA commands and ATA register accesses to a device.
*
- * 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.
- *
* History:
*
* 2002-10-19: Removed the specialized transfer routines.
@@ -60,9 +48,12 @@
#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);
@@ -76,7 +67,7 @@ static int isd200_Initialization(struct us_data *us);
{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
.driver_info = (flags) }
-static struct usb_device_id isd200_usb_ids[] = {
+static const struct usb_device_id isd200_usb_ids[] = {
# include "unusual_isd200.h"
{ } /* Terminating entry */
};
@@ -98,7 +89,7 @@ MODULE_DEVICE_TABLE(usb, isd200_usb_ids);
.initFunction = init_function, \
}
-static struct us_unusual_dev isd200_unusual_dev_list[] = {
+static const struct us_unusual_dev isd200_unusual_dev_list[] = {
# include "unusual_isd200.h"
{ } /* Terminating entry */
};
@@ -335,7 +326,7 @@ struct isd200_info {
/* maximum number of LUNs supported */
unsigned char MaxLUNs;
- unsigned char cmnd[BLK_MAX_CDB];
+ unsigned char cmnd[MAX_COMMAND_SIZE];
struct scsi_cmnd srb;
struct scatterlist sg;
};
@@ -494,7 +485,7 @@ static int isd200_action( struct us_data *us, int action,
int status;
memset(&ata, 0, sizeof(ata));
- srb->cmnd = info->cmnd;
+ memcpy(srb->cmnd, info->cmnd, MAX_COMMAND_SIZE);
srb->device = &srb_dev;
ata.generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
@@ -626,7 +617,8 @@ static void isd200_invoke_transport( struct us_data *us,
srb->cmd_len = sizeof(ataCdb->generic);
transferStatus = usb_stor_Bulk_transport(srb, us);
- /* if the command gets aborted by the higher layers, we need to
+ /*
+ * if the command gets aborted by the higher layers, we need to
* short-circuit all other processing
*/
if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
@@ -693,15 +685,18 @@ static void isd200_invoke_transport( struct us_data *us,
}
}
- /* Regardless of auto-sense, if we _know_ we have an error
+ /*
+ * Regardless of auto-sense, if we _know_ we have an error
* condition, show that in the result code
*/
if (transferStatus == USB_STOR_TRANSPORT_FAILED)
srb->result = SAM_STAT_CHECK_CONDITION;
return;
- /* abort processing: the bulk-only transport requires a reset
- * following an abort */
+ /*
+ * abort processing: the bulk-only transport requires a reset
+ * following an abort
+ */
Handle_Abort:
srb->result = DID_ABORT << 16;
@@ -737,7 +732,7 @@ static void isd200_log_config(struct us_data *us, struct isd200_info *info)
info->ConfigData.ATAExtraConfig & ATACFGE_CONF_DESC2);
usb_stor_dbg(us, " Skip Device Boot: 0x%x\n",
info->ConfigData.ATAExtraConfig & ATACFGE_SKIP_BOOT);
- usb_stor_dbg(us, " ATA 3 State Supsend: 0x%x\n",
+ usb_stor_dbg(us, " ATA 3 State Suspend: 0x%x\n",
info->ConfigData.ATAExtraConfig & ATACFGE_STATE_SUSPEND);
usb_stor_dbg(us, " Descriptor Override: 0x%x\n",
info->ConfigData.ATAExtraConfig & ATACFGE_DESC_OVERRIDE);
@@ -963,20 +958,22 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
info->DeviceHead = master_slave;
break;
}
- /* check Cylinder High/Low to
- determine if it is an ATAPI device
- */
+ /*
+ * check Cylinder High/Low to
+ * determine if it is an ATAPI device
+ */
else if (regs[ATA_REG_HCYL_OFFSET] == 0xEB &&
regs[ATA_REG_LCYL_OFFSET] == 0x14) {
- /* It seems that the RICOH
- MP6200A CD/RW drive will
- report itself okay as a
- slave when it is really a
- master. So this check again
- as a master device just to
- make sure it doesn't report
- itself okay as a master also
- */
+ /*
+ * It seems that the RICOH
+ * MP6200A CD/RW drive will
+ * report itself okay as a
+ * slave when it is really a
+ * master. So this check again
+ * as a master device just to
+ * make sure it doesn't report
+ * itself okay as a master also
+ */
if ((master_slave & ATA_ADDRESS_DEVHEAD_SLAVE) &&
!recheckAsMaster) {
usb_stor_dbg(us, " Identified ATAPI device as slave. Rechecking again as master\n");
@@ -1108,7 +1105,7 @@ static void isd200_dump_driveid(struct us_data *us, u16 *id)
static int isd200_get_inquiry_data( struct us_data *us )
{
struct isd200_info *info = (struct isd200_info *)us->extra;
- int retStatus = ISD200_GOOD;
+ int retStatus;
u16 *id = info->id;
usb_stor_dbg(us, "Entering isd200_get_inquiry_data\n");
@@ -1140,6 +1137,13 @@ static int isd200_get_inquiry_data( struct us_data *us )
isd200_fix_driveid(id);
isd200_dump_driveid(us, id);
+ /* Prevent division by 0 in isd200_scsi_to_ata() */
+ if (id[ATA_ID_HEADS] == 0 || id[ATA_ID_SECTORS] == 0) {
+ usb_stor_dbg(us, " Invalid ATA Identify data\n");
+ retStatus = ISD200_ERROR;
+ goto Done;
+ }
+
memset(&info->InquiryData, 0, sizeof(info->InquiryData));
/* Standard IDE interface only supports disks */
@@ -1157,7 +1161,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
/* Fill in vendor identification fields */
src = (__be16 *)&id[ATA_ID_PROD];
dest = (__u16*)info->InquiryData.VendorId;
- for (i=0;i<4;i++)
+ for (i = 0; i < 4; i++)
dest[i] = be16_to_cpu(src[i]);
src = (__be16 *)&id[ATA_ID_PROD + 8/2];
@@ -1174,9 +1178,11 @@ static int isd200_get_inquiry_data( struct us_data *us )
if (id[ATA_ID_COMMAND_SET_2] & COMMANDSET_MEDIA_STATUS) {
usb_stor_dbg(us, " Device supports Media Status Notification\n");
- /* Indicate that it is enabled, even though it is not
- * This allows the lock/unlock of the media to work
- * correctly.
+ /*
+ * Indicate that it is enabled, even
+ * though it is not.
+ * This allows the lock/unlock of the
+ * media to work correctly.
*/
info->DeviceFlags |= DF_MEDIA_STATUS_ENABLED;
}
@@ -1195,7 +1201,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
usb_stor_dbg(us, "Protocol changed to: %s\n",
us->protocol_name);
- /* Free driver structure */
+ /* Free driver structure */
us->extra_destructor(info);
kfree(info);
us->extra = NULL;
@@ -1203,6 +1209,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
}
}
+ Done:
usb_stor_dbg(us, "Leaving isd200_get_inquiry_data %08X\n", retStatus);
return(retStatus);
@@ -1384,7 +1391,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
isd200_srb_set_bufflen(srb, 0);
} else {
- usb_stor_dbg(us, " Not removeable media, just report okay\n");
+ usb_stor_dbg(us, " Not removable media, just report okay\n");
srb->result = SAM_STAT_GOOD;
sendToTransport = 0;
}
@@ -1450,34 +1457,30 @@ static void isd200_free_info_ptrs(void *info_)
* Allocates (if necessary) and initializes the driver structure.
*
* RETURNS:
- * ISD status code
+ * error status code
*/
static int isd200_init_info(struct us_data *us)
{
- int retStatus = ISD200_GOOD;
struct isd200_info *info;
info = kzalloc(sizeof(struct isd200_info), GFP_KERNEL);
if (!info)
- retStatus = ISD200_ERROR;
- else {
- info->id = kzalloc(ATA_ID_WORDS * 2, GFP_KERNEL);
- info->RegsBuf = kmalloc(sizeof(info->ATARegs), GFP_KERNEL);
- info->srb.sense_buffer =
- kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
- if (!info->id || !info->RegsBuf || !info->srb.sense_buffer) {
- isd200_free_info_ptrs(info);
- kfree(info);
- retStatus = ISD200_ERROR;
- }
- }
+ return -ENOMEM;
- if (retStatus == ISD200_GOOD) {
- us->extra = info;
- us->extra_destructor = isd200_free_info_ptrs;
+ info->id = kzalloc(ATA_ID_WORDS * 2, GFP_KERNEL);
+ info->RegsBuf = kmalloc(sizeof(info->ATARegs), GFP_KERNEL);
+ info->srb.sense_buffer = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
+
+ if (!info->id || !info->RegsBuf || !info->srb.sense_buffer) {
+ isd200_free_info_ptrs(info);
+ kfree(info);
+ return -ENOMEM;
}
- return retStatus;
+ us->extra = info;
+ us->extra_destructor = isd200_free_info_ptrs;
+
+ return 0;
}
/**************************************************************************
@@ -1486,22 +1489,27 @@ static int isd200_init_info(struct us_data *us)
static int isd200_Initialization(struct us_data *us)
{
+ int rc = 0;
+
usb_stor_dbg(us, "ISD200 Initialization...\n");
/* Initialize ISD200 info struct */
- if (isd200_init_info(us) == ISD200_ERROR) {
+ if (isd200_init_info(us) < 0) {
usb_stor_dbg(us, "ERROR Initializing ISD200 Info struct\n");
+ rc = -ENOMEM;
} else {
/* Get device specific data */
- if (isd200_get_inquiry_data(us) != ISD200_GOOD)
+ if (isd200_get_inquiry_data(us) != ISD200_GOOD) {
usb_stor_dbg(us, "ISD200 Initialization Failure\n");
- else
+ rc = -EINVAL;
+ } else {
usb_stor_dbg(us, "ISD200 Initialization complete\n");
+ }
}
- return 0;
+ return rc;
}
@@ -1517,13 +1525,16 @@ static int isd200_Initialization(struct us_data *us)
static void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us)
{
- int sendToTransport = 1, orig_bufflen;
+ int sendToTransport, orig_bufflen;
union ata_cdb ataCdb;
/* Make sure driver was initialized */
- if (us->extra == NULL)
+ if (us->extra == NULL) {
usb_stor_dbg(us, "ERROR Driver not initialized\n");
+ srb->result = DID_ERROR << 16;
+ return;
+ }
scsi_set_resid(srb, 0);
/* scsi_bufflen might change in protocol translation to ata */
@@ -1537,6 +1548,8 @@ static void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us)
isd200_srb_set_bufflen(srb, orig_bufflen);
}
+static struct scsi_host_template isd200_host_template;
+
static int isd200_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -1544,7 +1557,8 @@ static int isd200_probe(struct usb_interface *intf,
int result;
result = usb_stor_probe1(&us, intf, id,
- (id - isd200_usb_ids) + isd200_unusual_dev_list);
+ (id - isd200_usb_ids) + isd200_unusual_dev_list,
+ &isd200_host_template);
if (result)
return result;
@@ -1556,7 +1570,7 @@ static int isd200_probe(struct usb_interface *intf,
}
static struct usb_driver isd200_driver = {
- .name = "ums-isd200",
+ .name = DRV_NAME,
.probe = isd200_probe,
.disconnect = usb_stor_disconnect,
.suspend = usb_stor_suspend,
@@ -1569,4 +1583,4 @@ static struct usb_driver isd200_driver = {
.no_dynamic_id = 1,
};
-module_usb_driver(isd200_driver);
+module_usb_stor_driver(isd200_driver, isd200_host_template, DRV_NAME);