Commit a4adae52 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

[PATCH] USB: storage: Revised update to isd200 I/O buffer patch

This is a minor revision to the previous patch as83.  It changes the name
of the various struct hd_driveid variables from 'drive' to 'id', per
Andries Brouwer's request.

 - Don't do DMA into the middle of a structure (info->drive).
 - Don't use I/O buffers for two different purposes simultaneously
 	(info->ATARegs, regs, us->iobuf).
 - Rename info->drive to info->id.
parent 0c2dfb88
...@@ -272,8 +272,9 @@ struct isd200_config { ...@@ -272,8 +272,9 @@ struct isd200_config {
struct isd200_info { struct isd200_info {
struct inquiry_data InquiryData; struct inquiry_data InquiryData;
struct hd_driveid drive; struct hd_driveid *id;
struct isd200_config ConfigData; struct isd200_config ConfigData;
unsigned char *RegsBuf;
unsigned char ATARegs[8]; unsigned char ATARegs[8];
unsigned char DeviceHead; unsigned char DeviceHead;
unsigned char DeviceFlags; unsigned char DeviceFlags;
...@@ -473,7 +474,7 @@ static int isd200_action( struct us_data *us, int action, ...@@ -473,7 +474,7 @@ static int isd200_action( struct us_data *us, int action,
ata.generic.RegisterSelect = REG_COMMAND; ata.generic.RegisterSelect = REG_COMMAND;
ata.write.CommandByte = WIN_IDENTIFY; ata.write.CommandByte = WIN_IDENTIFY;
srb->sc_data_direction = SCSI_DATA_READ; srb->sc_data_direction = SCSI_DATA_READ;
srb->request_buffer = (void *)&info->drive; srb->request_buffer = (void *) info->id;
srb->request_bufflen = sizeof(struct hd_driveid); srb->request_bufflen = sizeof(struct hd_driveid);
break; break;
...@@ -513,11 +514,12 @@ int isd200_read_regs( struct us_data *us ) ...@@ -513,11 +514,12 @@ int isd200_read_regs( struct us_data *us )
US_DEBUGP("Entering isd200_IssueATAReadRegs\n"); US_DEBUGP("Entering isd200_IssueATAReadRegs\n");
transferStatus = isd200_action( us, ACTION_READ_STATUS, transferStatus = isd200_action( us, ACTION_READ_STATUS,
info->ATARegs, sizeof(info->ATARegs) ); info->RegsBuf, sizeof(info->ATARegs) );
if (transferStatus != ISD200_TRANSPORT_GOOD) { if (transferStatus != ISD200_TRANSPORT_GOOD) {
US_DEBUGP(" Error reading ATA registers\n"); US_DEBUGP(" Error reading ATA registers\n");
retStatus = ISD200_ERROR; retStatus = ISD200_ERROR;
} else { } else {
memcpy(info->ATARegs, info->RegsBuf, sizeof(info->ATARegs));
US_DEBUGP(" Got ATA Register[IDE_ERROR_OFFSET] = 0x%x\n", US_DEBUGP(" Got ATA Register[IDE_ERROR_OFFSET] = 0x%x\n",
info->ATARegs[IDE_ERROR_OFFSET]); info->ATARegs[IDE_ERROR_OFFSET]);
} }
...@@ -835,9 +837,9 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave, ...@@ -835,9 +837,9 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
int detect ) int detect )
{ {
int status = ISD200_GOOD; int status = ISD200_GOOD;
unsigned char *regs = us->iobuf;
unsigned long endTime; unsigned long endTime;
struct isd200_info *info = (struct isd200_info *)us->extra; struct isd200_info *info = (struct isd200_info *)us->extra;
unsigned char *regs = info->RegsBuf;
int recheckAsMaster = FALSE; int recheckAsMaster = FALSE;
if ( detect ) if ( detect )
...@@ -984,6 +986,7 @@ int isd200_get_inquiry_data( struct us_data *us ) ...@@ -984,6 +986,7 @@ int isd200_get_inquiry_data( struct us_data *us )
{ {
struct isd200_info *info = (struct isd200_info *)us->extra; struct isd200_info *info = (struct isd200_info *)us->extra;
int retStatus = ISD200_GOOD; int retStatus = ISD200_GOOD;
struct hd_driveid *id = info->id;
US_DEBUGP("Entering isd200_get_inquiry_data\n"); US_DEBUGP("Entering isd200_get_inquiry_data\n");
...@@ -1000,7 +1003,7 @@ int isd200_get_inquiry_data( struct us_data *us ) ...@@ -1000,7 +1003,7 @@ int isd200_get_inquiry_data( struct us_data *us )
/* this must be an ATA device */ /* this must be an ATA device */
/* perform an ATA Command Identify */ /* perform an ATA Command Identify */
transferStatus = isd200_action( us, ACTION_IDENTIFY, transferStatus = isd200_action( us, ACTION_IDENTIFY,
&info->drive, id,
sizeof(struct hd_driveid) ); sizeof(struct hd_driveid) );
if (transferStatus != ISD200_TRANSPORT_GOOD) { if (transferStatus != ISD200_TRANSPORT_GOOD) {
/* Error issuing ATA Command Identify */ /* Error issuing ATA Command Identify */
...@@ -1010,35 +1013,35 @@ int isd200_get_inquiry_data( struct us_data *us ) ...@@ -1010,35 +1013,35 @@ int isd200_get_inquiry_data( struct us_data *us )
/* ATA Command Identify successful */ /* ATA Command Identify successful */
int i; int i;
__u16 *src, *dest; __u16 *src, *dest;
ide_fix_driveid(&info->drive); ide_fix_driveid(id);
US_DEBUGP(" Identify Data Structure:\n"); US_DEBUGP(" Identify Data Structure:\n");
US_DEBUGP(" config = 0x%x\n", info->drive.config); US_DEBUGP(" config = 0x%x\n", id->config);
US_DEBUGP(" cyls = 0x%x\n", info->drive.cyls); US_DEBUGP(" cyls = 0x%x\n", id->cyls);
US_DEBUGP(" heads = 0x%x\n", info->drive.heads); US_DEBUGP(" heads = 0x%x\n", id->heads);
US_DEBUGP(" track_bytes = 0x%x\n", info->drive.track_bytes); US_DEBUGP(" track_bytes = 0x%x\n", id->track_bytes);
US_DEBUGP(" sector_bytes = 0x%x\n", info->drive.sector_bytes); US_DEBUGP(" sector_bytes = 0x%x\n", id->sector_bytes);
US_DEBUGP(" sectors = 0x%x\n", info->drive.sectors); US_DEBUGP(" sectors = 0x%x\n", id->sectors);
US_DEBUGP(" serial_no[0] = 0x%x\n", info->drive.serial_no[0]); US_DEBUGP(" serial_no[0] = 0x%x\n", id->serial_no[0]);
US_DEBUGP(" buf_type = 0x%x\n", info->drive.buf_type); US_DEBUGP(" buf_type = 0x%x\n", id->buf_type);
US_DEBUGP(" buf_size = 0x%x\n", info->drive.buf_size); US_DEBUGP(" buf_size = 0x%x\n", id->buf_size);
US_DEBUGP(" ecc_bytes = 0x%x\n", info->drive.ecc_bytes); US_DEBUGP(" ecc_bytes = 0x%x\n", id->ecc_bytes);
US_DEBUGP(" fw_rev[0] = 0x%x\n", info->drive.fw_rev[0]); US_DEBUGP(" fw_rev[0] = 0x%x\n", id->fw_rev[0]);
US_DEBUGP(" model[0] = 0x%x\n", info->drive.model[0]); US_DEBUGP(" model[0] = 0x%x\n", id->model[0]);
US_DEBUGP(" max_multsect = 0x%x\n", info->drive.max_multsect); US_DEBUGP(" max_multsect = 0x%x\n", id->max_multsect);
US_DEBUGP(" dword_io = 0x%x\n", info->drive.dword_io); US_DEBUGP(" dword_io = 0x%x\n", id->dword_io);
US_DEBUGP(" capability = 0x%x\n", info->drive.capability); US_DEBUGP(" capability = 0x%x\n", id->capability);
US_DEBUGP(" tPIO = 0x%x\n", info->drive.tPIO); US_DEBUGP(" tPIO = 0x%x\n", id->tPIO);
US_DEBUGP(" tDMA = 0x%x\n", info->drive.tDMA); US_DEBUGP(" tDMA = 0x%x\n", id->tDMA);
US_DEBUGP(" field_valid = 0x%x\n", info->drive.field_valid); US_DEBUGP(" field_valid = 0x%x\n", id->field_valid);
US_DEBUGP(" cur_cyls = 0x%x\n", info->drive.cur_cyls); US_DEBUGP(" cur_cyls = 0x%x\n", id->cur_cyls);
US_DEBUGP(" cur_heads = 0x%x\n", info->drive.cur_heads); US_DEBUGP(" cur_heads = 0x%x\n", id->cur_heads);
US_DEBUGP(" cur_sectors = 0x%x\n", info->drive.cur_sectors); US_DEBUGP(" cur_sectors = 0x%x\n", id->cur_sectors);
US_DEBUGP(" cur_capacity = 0x%x\n", (info->drive.cur_capacity1 << 16) + info->drive.cur_capacity0 ); US_DEBUGP(" cur_capacity = 0x%x\n", (id->cur_capacity1 << 16) + id->cur_capacity0 );
US_DEBUGP(" multsect = 0x%x\n", info->drive.multsect); US_DEBUGP(" multsect = 0x%x\n", id->multsect);
US_DEBUGP(" lba_capacity = 0x%x\n", info->drive.lba_capacity); US_DEBUGP(" lba_capacity = 0x%x\n", id->lba_capacity);
US_DEBUGP(" command_set_1 = 0x%x\n", info->drive.command_set_1); US_DEBUGP(" command_set_1 = 0x%x\n", id->command_set_1);
US_DEBUGP(" command_set_2 = 0x%x\n", info->drive.command_set_2); US_DEBUGP(" command_set_2 = 0x%x\n", id->command_set_2);
memset(&info->InquiryData, 0, sizeof(info->InquiryData)); memset(&info->InquiryData, 0, sizeof(info->InquiryData));
...@@ -1054,30 +1057,30 @@ int isd200_get_inquiry_data( struct us_data *us ) ...@@ -1054,30 +1057,30 @@ int isd200_get_inquiry_data( struct us_data *us )
/* The length must be at least 36 (5 + 31) */ /* The length must be at least 36 (5 + 31) */
info->InquiryData.AdditionalLength = 0x1F; info->InquiryData.AdditionalLength = 0x1F;
if (info->drive.command_set_1 & COMMANDSET_MEDIA_STATUS) { if (id->command_set_1 & COMMANDSET_MEDIA_STATUS) {
/* set the removable bit */ /* set the removable bit */
info->InquiryData.DeviceTypeModifier = DEVICE_REMOVABLE; info->InquiryData.DeviceTypeModifier = DEVICE_REMOVABLE;
info->DeviceFlags |= DF_REMOVABLE_MEDIA; info->DeviceFlags |= DF_REMOVABLE_MEDIA;
} }
/* Fill in vendor identification fields */ /* Fill in vendor identification fields */
src = (__u16*)info->drive.model; src = (__u16*)id->model;
dest = (__u16*)info->InquiryData.VendorId; dest = (__u16*)info->InquiryData.VendorId;
for (i=0;i<4;i++) for (i=0;i<4;i++)
dest[i] = be16_to_cpu(src[i]); dest[i] = be16_to_cpu(src[i]);
src = (__u16*)(info->drive.model+8); src = (__u16*)(id->model+8);
dest = (__u16*)info->InquiryData.ProductId; dest = (__u16*)info->InquiryData.ProductId;
for (i=0;i<8;i++) for (i=0;i<8;i++)
dest[i] = be16_to_cpu(src[i]); dest[i] = be16_to_cpu(src[i]);
src = (__u16*)info->drive.fw_rev; src = (__u16*)id->fw_rev;
dest = (__u16*)info->InquiryData.ProductRevisionLevel; dest = (__u16*)info->InquiryData.ProductRevisionLevel;
for (i=0;i<2;i++) for (i=0;i<2;i++)
dest[i] = be16_to_cpu(src[i]); dest[i] = be16_to_cpu(src[i]);
/* determine if it supports Media Status Notification */ /* determine if it supports Media Status Notification */
if (info->drive.command_set_2 & COMMANDSET_MEDIA_STATUS) { if (id->command_set_2 & COMMANDSET_MEDIA_STATUS) {
US_DEBUGP(" Device supports Media Status Notification\n"); US_DEBUGP(" Device supports Media Status Notification\n");
/* Indicate that it is enabled, even though it is not /* Indicate that it is enabled, even though it is not
...@@ -1101,13 +1104,11 @@ int isd200_get_inquiry_data( struct us_data *us ) ...@@ -1101,13 +1104,11 @@ int isd200_get_inquiry_data( struct us_data *us )
US_DEBUGP("Protocol changed to: %s\n", us->protocol_name); US_DEBUGP("Protocol changed to: %s\n", us->protocol_name);
/* Free driver structure */ /* Free driver structure */
if (us->extra != NULL) { us->extra_destructor(info);
kfree(us->extra);
us->extra = NULL; us->extra = NULL;
us->extra_destructor = NULL; us->extra_destructor = NULL;
} }
} }
}
US_DEBUGP("Leaving isd200_get_inquiry_data %08X\n", retStatus); US_DEBUGP("Leaving isd200_get_inquiry_data %08X\n", retStatus);
...@@ -1182,6 +1183,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, ...@@ -1182,6 +1183,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
union ata_cdb * ataCdb) union ata_cdb * ataCdb)
{ {
struct isd200_info *info = (struct isd200_info *)us->extra; struct isd200_info *info = (struct isd200_info *)us->extra;
struct hd_driveid *id = info->id;
int sendToTransport = TRUE; int sendToTransport = TRUE;
unsigned char sectnum, head; unsigned char sectnum, head;
unsigned short cylinder; unsigned short cylinder;
...@@ -1254,12 +1256,12 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, ...@@ -1254,12 +1256,12 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
US_DEBUGP(" ATA OUT - SCSIOP_READ_CAPACITY\n"); US_DEBUGP(" ATA OUT - SCSIOP_READ_CAPACITY\n");
if (info->drive.capability & CAPABILITY_LBA ) { if (id->capability & CAPABILITY_LBA ) {
capacity = info->drive.lba_capacity - 1; capacity = id->lba_capacity - 1;
} else { } else {
capacity = (info->drive.heads * capacity = (id->heads *
info->drive.cyls * id->cyls *
info->drive.sectors) - 1; id->sectors) - 1;
} }
readCapacityData.LogicalBlockAddress = cpu_to_be32(capacity); readCapacityData.LogicalBlockAddress = cpu_to_be32(capacity);
readCapacityData.BytesPerBlock = cpu_to_be32(0x200); readCapacityData.BytesPerBlock = cpu_to_be32(0x200);
...@@ -1280,16 +1282,16 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, ...@@ -1280,16 +1282,16 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
lba = cpu_to_be32(lba); lba = cpu_to_be32(lba);
blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8]; blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8];
if (info->drive.capability & CAPABILITY_LBA) { if (id->capability & CAPABILITY_LBA) {
sectnum = (unsigned char)(lba); sectnum = (unsigned char)(lba);
cylinder = (unsigned short)(lba>>8); cylinder = (unsigned short)(lba>>8);
head = ATA_ADDRESS_DEVHEAD_LBA_MODE | (unsigned char)(lba>>24 & 0x0F); head = ATA_ADDRESS_DEVHEAD_LBA_MODE | (unsigned char)(lba>>24 & 0x0F);
} else { } else {
sectnum = (unsigned char)((lba % info->drive.sectors) + 1); sectnum = (unsigned char)((lba % id->sectors) + 1);
cylinder = (unsigned short)(lba / (info->drive.sectors * cylinder = (unsigned short)(lba / (id->sectors *
info->drive.heads)); id->heads));
head = (unsigned char)((lba / info->drive.sectors) % head = (unsigned char)((lba / id->sectors) %
info->drive.heads); id->heads);
} }
ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand; ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand; ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
...@@ -1313,14 +1315,14 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, ...@@ -1313,14 +1315,14 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
lba = cpu_to_be32(lba); lba = cpu_to_be32(lba);
blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8]; blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8];
if (info->drive.capability & CAPABILITY_LBA) { if (id->capability & CAPABILITY_LBA) {
sectnum = (unsigned char)(lba); sectnum = (unsigned char)(lba);
cylinder = (unsigned short)(lba>>8); cylinder = (unsigned short)(lba>>8);
head = ATA_ADDRESS_DEVHEAD_LBA_MODE | (unsigned char)(lba>>24 & 0x0F); head = ATA_ADDRESS_DEVHEAD_LBA_MODE | (unsigned char)(lba>>24 & 0x0F);
} else { } else {
sectnum = (unsigned char)((lba % info->drive.sectors) + 1); sectnum = (unsigned char)((lba % id->sectors) + 1);
cylinder = (unsigned short)(lba / (info->drive.sectors * info->drive.heads)); cylinder = (unsigned short)(lba / (id->sectors * id->heads));
head = (unsigned char)((lba / info->drive.sectors) % info->drive.heads); head = (unsigned char)((lba / id->sectors) % id->heads);
} }
ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand; ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand; ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
...@@ -1397,6 +1399,21 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, ...@@ -1397,6 +1399,21 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
} }
/**************************************************************************
* isd200_free_info
*
* Frees the driver structure.
*/
void isd200_free_info_ptrs(void *info_)
{
struct isd200_info *info = (struct isd200_info *) info_;
if (info) {
kfree(info->id);
kfree(info->RegsBuf);
}
}
/************************************************************************** /**************************************************************************
* isd200_init_info * isd200_init_info
* *
...@@ -1408,18 +1425,31 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, ...@@ -1408,18 +1425,31 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
int isd200_init_info(struct us_data *us) int isd200_init_info(struct us_data *us)
{ {
int retStatus = ISD200_GOOD; int retStatus = ISD200_GOOD;
struct isd200_info *info;
if (!us->extra) { info = (struct isd200_info *)
us->extra = (void *) kmalloc(sizeof(struct isd200_info), GFP_KERNEL); kmalloc(sizeof(struct isd200_info), GFP_KERNEL);
if (!us->extra) { if (!info)
US_DEBUGP("ERROR - kmalloc failure\n");
retStatus = ISD200_ERROR; retStatus = ISD200_ERROR;
} else {
memset(info, 0, sizeof(struct isd200_info));
info->id = (struct hd_driveid *)
kmalloc(sizeof(struct hd_driveid), GFP_KERNEL);
info->RegsBuf = (unsigned char *)
kmalloc(sizeof(info->ATARegs), GFP_KERNEL);
if (!info->id || !info->RegsBuf) {
isd200_free_info_ptrs(info);
kfree(info);
retStatus = ISD200_ERROR;
} else
memset(info->id, 0, sizeof(struct hd_driveid));
} }
if (retStatus == ISD200_GOOD) { if (retStatus == ISD200_GOOD) {
memset(us->extra, 0, sizeof(struct isd200_info)); us->extra = info;
} us->extra_destructor = isd200_free_info_ptrs;
} else
US_DEBUGP("ERROR - kmalloc failure\n");
return(retStatus); return(retStatus);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment