Commit 48c23d3e authored by Boaz Harrosh's avatar Boaz Harrosh Committed by James Bottomley

[SCSI] isd200: use one-element sg list in issuing commands

  - This patch should be commited before:
    usb: transport - convert to accessors and !use_sg code path removal

  - isd200_action() was still using direct liniar pointers in issuing
    commands to the USB transport level. This is no longer supported,
    use one-element scatterlist instead.
  - Adjustment of command's length in the case of scsi-to-ata translation
    is now restored before return to queuecommand, since other wise it can
    leak BIOs.
  - isd200_action() return Error on unknown requests. Used to print an error
    but still try to send garbage cdb.
  - convert few places to scsi data accessors.
  - Todo: This file will need to be changed when scsi_cmnd changes to
    scsi_data_buffer or any other solution.
Signed-off-by: default avatarBoaz Harrosh <bharrosh@panasas.com>
Acked-by: default avatarMatthew Dharm <mdharm-scsi@one-eyed-alien.net>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 6d416e61
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/scatterlist.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h> #include <scsi/scsi_cmnd.h>
...@@ -287,6 +288,7 @@ struct isd200_info { ...@@ -287,6 +288,7 @@ struct isd200_info {
/* maximum number of LUNs supported */ /* maximum number of LUNs supported */
unsigned char MaxLUNs; unsigned char MaxLUNs;
struct scsi_cmnd srb; struct scsi_cmnd srb;
struct scatterlist sg;
}; };
...@@ -398,6 +400,31 @@ static void isd200_build_sense(struct us_data *us, struct scsi_cmnd *srb) ...@@ -398,6 +400,31 @@ static void isd200_build_sense(struct us_data *us, struct scsi_cmnd *srb)
* Transport routines * 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)
{
struct scsi_cmnd *srb = &info->srb;
if (buff)
sg_init_one(&info->sg, buff, bufflen);
srb->sc_data_direction = dir;
srb->request_buffer = buff ? &info->sg : NULL;
srb->request_bufflen = bufflen;
srb->use_sg = buff ? 1 : 0;
}
static void isd200_srb_set_bufflen(struct scsi_cmnd *srb, unsigned bufflen)
{
srb->request_bufflen = bufflen;
}
/************************************************************************** /**************************************************************************
* isd200_action * isd200_action
...@@ -432,9 +459,7 @@ static int isd200_action( struct us_data *us, int action, ...@@ -432,9 +459,7 @@ static int isd200_action( struct us_data *us, int action,
ata.generic.RegisterSelect = ata.generic.RegisterSelect =
REG_CYLINDER_LOW | REG_CYLINDER_HIGH | REG_CYLINDER_LOW | REG_CYLINDER_HIGH |
REG_STATUS | REG_ERROR; REG_STATUS | REG_ERROR;
srb->sc_data_direction = DMA_FROM_DEVICE; isd200_set_srb(info, DMA_FROM_DEVICE, pointer, value);
srb->request_buffer = pointer;
srb->request_bufflen = value;
break; break;
case ACTION_ENUM: case ACTION_ENUM:
...@@ -444,7 +469,7 @@ static int isd200_action( struct us_data *us, int action, ...@@ -444,7 +469,7 @@ static int isd200_action( struct us_data *us, int action,
ACTION_SELECT_5; ACTION_SELECT_5;
ata.generic.RegisterSelect = REG_DEVICE_HEAD; ata.generic.RegisterSelect = REG_DEVICE_HEAD;
ata.write.DeviceHeadByte = value; ata.write.DeviceHeadByte = value;
srb->sc_data_direction = DMA_NONE; isd200_set_srb(info, DMA_NONE, NULL, 0);
break; break;
case ACTION_RESET: case ACTION_RESET:
...@@ -453,7 +478,7 @@ static int isd200_action( struct us_data *us, int action, ...@@ -453,7 +478,7 @@ static int isd200_action( struct us_data *us, int action,
ACTION_SELECT_3|ACTION_SELECT_4; ACTION_SELECT_3|ACTION_SELECT_4;
ata.generic.RegisterSelect = REG_DEVICE_CONTROL; ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
ata.write.DeviceControlByte = ATA_DC_RESET_CONTROLLER; ata.write.DeviceControlByte = ATA_DC_RESET_CONTROLLER;
srb->sc_data_direction = DMA_NONE; isd200_set_srb(info, DMA_NONE, NULL, 0);
break; break;
case ACTION_REENABLE: case ACTION_REENABLE:
...@@ -462,7 +487,7 @@ static int isd200_action( struct us_data *us, int action, ...@@ -462,7 +487,7 @@ static int isd200_action( struct us_data *us, int action,
ACTION_SELECT_3|ACTION_SELECT_4; ACTION_SELECT_3|ACTION_SELECT_4;
ata.generic.RegisterSelect = REG_DEVICE_CONTROL; ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
ata.write.DeviceControlByte = ATA_DC_REENABLE_CONTROLLER; ata.write.DeviceControlByte = ATA_DC_REENABLE_CONTROLLER;
srb->sc_data_direction = DMA_NONE; isd200_set_srb(info, DMA_NONE, NULL, 0);
break; break;
case ACTION_SOFT_RESET: case ACTION_SOFT_RESET:
...@@ -471,21 +496,20 @@ static int isd200_action( struct us_data *us, int action, ...@@ -471,21 +496,20 @@ static int isd200_action( struct us_data *us, int action,
ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND; ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND;
ata.write.DeviceHeadByte = info->DeviceHead; ata.write.DeviceHeadByte = info->DeviceHead;
ata.write.CommandByte = WIN_SRST; ata.write.CommandByte = WIN_SRST;
srb->sc_data_direction = DMA_NONE; isd200_set_srb(info, DMA_NONE, NULL, 0);
break; break;
case ACTION_IDENTIFY: case ACTION_IDENTIFY:
US_DEBUGP(" isd200_action(IDENTIFY)\n"); US_DEBUGP(" isd200_action(IDENTIFY)\n");
ata.generic.RegisterSelect = REG_COMMAND; ata.generic.RegisterSelect = REG_COMMAND;
ata.write.CommandByte = WIN_IDENTIFY; ata.write.CommandByte = WIN_IDENTIFY;
srb->sc_data_direction = DMA_FROM_DEVICE; isd200_set_srb(info, DMA_FROM_DEVICE, info->id,
srb->request_buffer = (void *) info->id; sizeof(struct hd_driveid));
srb->request_bufflen = sizeof(struct hd_driveid);
break; break;
default: default:
US_DEBUGP("Error: Undefined action %d\n",action); US_DEBUGP("Error: Undefined action %d\n",action);
break; return ISD200_ERROR;
} }
memcpy(srb->cmnd, &ata, sizeof(ata.generic)); memcpy(srb->cmnd, &ata, sizeof(ata.generic));
...@@ -590,7 +614,7 @@ static void isd200_invoke_transport( struct us_data *us, ...@@ -590,7 +614,7 @@ static void isd200_invoke_transport( struct us_data *us,
return; return;
} }
if ((srb->resid > 0) && if ((scsi_get_resid(srb) > 0) &&
!((srb->cmnd[0] == REQUEST_SENSE) || !((srb->cmnd[0] == REQUEST_SENSE) ||
(srb->cmnd[0] == INQUIRY) || (srb->cmnd[0] == INQUIRY) ||
(srb->cmnd[0] == MODE_SENSE) || (srb->cmnd[0] == MODE_SENSE) ||
...@@ -1217,7 +1241,6 @@ static int isd200_get_inquiry_data( struct us_data *us ) ...@@ -1217,7 +1241,6 @@ static int isd200_get_inquiry_data( struct us_data *us )
return(retStatus); return(retStatus);
} }
/************************************************************************** /**************************************************************************
* isd200_scsi_to_ata * isd200_scsi_to_ata
* *
...@@ -1266,7 +1289,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us, ...@@ -1266,7 +1289,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
ataCdb->generic.TransferBlockSize = 1; ataCdb->generic.TransferBlockSize = 1;
ataCdb->generic.RegisterSelect = REG_COMMAND; ataCdb->generic.RegisterSelect = REG_COMMAND;
ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS; ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
srb->request_bufflen = 0; isd200_srb_set_bufflen(srb, 0);
} else { } else {
US_DEBUGP(" Media Status not supported, just report okay\n"); US_DEBUGP(" Media Status not supported, just report okay\n");
srb->result = SAM_STAT_GOOD; srb->result = SAM_STAT_GOOD;
...@@ -1284,7 +1307,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us, ...@@ -1284,7 +1307,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
ataCdb->generic.TransferBlockSize = 1; ataCdb->generic.TransferBlockSize = 1;
ataCdb->generic.RegisterSelect = REG_COMMAND; ataCdb->generic.RegisterSelect = REG_COMMAND;
ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS; ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
srb->request_bufflen = 0; isd200_srb_set_bufflen(srb, 0);
} else { } else {
US_DEBUGP(" Media Status not supported, just report okay\n"); US_DEBUGP(" Media Status not supported, just report okay\n");
srb->result = SAM_STAT_GOOD; srb->result = SAM_STAT_GOOD;
...@@ -1390,7 +1413,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us, ...@@ -1390,7 +1413,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
ataCdb->generic.RegisterSelect = REG_COMMAND; ataCdb->generic.RegisterSelect = REG_COMMAND;
ataCdb->write.CommandByte = (srb->cmnd[4] & 0x1) ? ataCdb->write.CommandByte = (srb->cmnd[4] & 0x1) ?
WIN_DOORLOCK : WIN_DOORUNLOCK; WIN_DOORLOCK : WIN_DOORUNLOCK;
srb->request_bufflen = 0; isd200_srb_set_bufflen(srb, 0);
} else { } else {
US_DEBUGP(" Not removeable media, just report okay\n"); US_DEBUGP(" Not removeable media, just report okay\n");
srb->result = SAM_STAT_GOOD; srb->result = SAM_STAT_GOOD;
...@@ -1416,7 +1439,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us, ...@@ -1416,7 +1439,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
ataCdb->generic.TransferBlockSize = 1; ataCdb->generic.TransferBlockSize = 1;
ataCdb->generic.RegisterSelect = REG_COMMAND; ataCdb->generic.RegisterSelect = REG_COMMAND;
ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS; ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
srb->request_bufflen = 0; isd200_srb_set_bufflen(srb, 0);
} else { } else {
US_DEBUGP(" Nothing to do, just report okay\n"); US_DEBUGP(" Nothing to do, just report okay\n");
srb->result = SAM_STAT_GOOD; srb->result = SAM_STAT_GOOD;
...@@ -1525,7 +1548,7 @@ int isd200_Initialization(struct us_data *us) ...@@ -1525,7 +1548,7 @@ int isd200_Initialization(struct us_data *us)
void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us)
{ {
int sendToTransport = 1; int sendToTransport = 1, orig_bufflen;
union ata_cdb ataCdb; union ata_cdb ataCdb;
/* Make sure driver was initialized */ /* Make sure driver was initialized */
...@@ -1533,11 +1556,14 @@ void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) ...@@ -1533,11 +1556,14 @@ void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us)
if (us->extra == NULL) if (us->extra == NULL)
US_DEBUGP("ERROR Driver not initialized\n"); US_DEBUGP("ERROR Driver not initialized\n");
/* Convert command */ scsi_set_resid(srb, 0);
srb->resid = 0; /* scsi_bufflen might change in protocol translation to ata */
orig_bufflen = scsi_bufflen(srb);
sendToTransport = isd200_scsi_to_ata(srb, us, &ataCdb); sendToTransport = isd200_scsi_to_ata(srb, us, &ataCdb);
/* send the command to the transport layer */ /* send the command to the transport layer */
if (sendToTransport) if (sendToTransport)
isd200_invoke_transport(us, srb, &ataCdb); isd200_invoke_transport(us, srb, &ataCdb);
isd200_srb_set_bufflen(srb, orig_bufflen);
} }
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