diff options
Diffstat (limited to 'drivers/usb/storage/isd200.c')
| -rw-r--r-- | drivers/usb/storage/isd200.c | 154 |
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); |
