- Update to 2.6.25-rc3.
[linux-flexiantxendom0-3.2.10.git] / drivers / usb / storage / isd200.c
index 49ba6c0..2ae1e86 100644 (file)
@@ -48,7 +48,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/hdreg.h>
-#include <linux/ide.h>
+#include <linux/scatterlist.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #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
 
@@ -287,6 +293,7 @@ struct isd200_info {
        /* maximum number of LUNs supported */
        unsigned char MaxLUNs;
        struct scsi_cmnd srb;
+       struct scatterlist sg;
 };
 
 
@@ -358,7 +365,7 @@ static void isd200_build_sense(struct us_data *us, struct scsi_cmnd *srb)
 {
        struct isd200_info *info = (struct isd200_info *)us->extra;
        struct sense_data *buf = (struct sense_data *) &srb->sense_buffer[0];
-       unsigned char error = info->ATARegs[IDE_ERROR_OFFSET];
+       unsigned char error = info->ATARegs[ATA_REG_ERROR_OFFSET];
 
        if(error & ATA_ERROR_MEDIA_CHANGE) {
                buf->ErrorCode = 0x70 | SENSE_ERRCODE_VALID;
@@ -398,6 +405,31 @@ static void isd200_build_sense(struct us_data *us, struct scsi_cmnd *srb)
  * 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->sdb.table.sgl = buff ? &info->sg : NULL;
+       srb->sdb.length = bufflen;
+       srb->sdb.table.nents = buff ? 1 : 0;
+}
+
+static void isd200_srb_set_bufflen(struct scsi_cmnd *srb, unsigned bufflen)
+{
+       srb->sdb.length = bufflen;
+}
+
 
 /**************************************************************************
  *  isd200_action
@@ -432,9 +464,7 @@ static int isd200_action( struct us_data *us, int action,
                ata.generic.RegisterSelect =
                  REG_CYLINDER_LOW | REG_CYLINDER_HIGH |
                  REG_STATUS | REG_ERROR;
-               srb->sc_data_direction = DMA_FROM_DEVICE;
-               srb->request_buffer = pointer;
-               srb->request_bufflen = value;
+               isd200_set_srb(info, DMA_FROM_DEVICE, pointer, value);
                break;
 
        case ACTION_ENUM:
@@ -444,7 +474,7 @@ static int isd200_action( struct us_data *us, int action,
                                           ACTION_SELECT_5;
                ata.generic.RegisterSelect = REG_DEVICE_HEAD;
                ata.write.DeviceHeadByte = value;
-               srb->sc_data_direction = DMA_NONE;
+               isd200_set_srb(info, DMA_NONE, NULL, 0);
                break;
 
        case ACTION_RESET:
@@ -453,7 +483,7 @@ static int isd200_action( struct us_data *us, int action,
                                           ACTION_SELECT_3|ACTION_SELECT_4;
                ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
                ata.write.DeviceControlByte = ATA_DC_RESET_CONTROLLER;
-               srb->sc_data_direction = DMA_NONE;
+               isd200_set_srb(info, DMA_NONE, NULL, 0);
                break;
 
        case ACTION_REENABLE:
@@ -462,7 +492,7 @@ static int isd200_action( struct us_data *us, int action,
                                           ACTION_SELECT_3|ACTION_SELECT_4;
                ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
                ata.write.DeviceControlByte = ATA_DC_REENABLE_CONTROLLER;
-               srb->sc_data_direction = DMA_NONE;
+               isd200_set_srb(info, DMA_NONE, NULL, 0);
                break;
 
        case ACTION_SOFT_RESET:
@@ -471,21 +501,20 @@ static int isd200_action( struct us_data *us, int action,
                ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND;
                ata.write.DeviceHeadByte = info->DeviceHead;
                ata.write.CommandByte = WIN_SRST;
-               srb->sc_data_direction = DMA_NONE;
+               isd200_set_srb(info, DMA_NONE, NULL, 0);
                break;
 
        case ACTION_IDENTIFY:
                US_DEBUGP("   isd200_action(IDENTIFY)\n");
                ata.generic.RegisterSelect = REG_COMMAND;
                ata.write.CommandByte = WIN_IDENTIFY;
-               srb->sc_data_direction = DMA_FROM_DEVICE;
-               srb->request_buffer = (void *) info->id;
-               srb->request_bufflen = sizeof(struct hd_driveid);
+               isd200_set_srb(info, DMA_FROM_DEVICE, info->id,
+                                               sizeof(struct hd_driveid));
                break;
 
        default:
                US_DEBUGP("Error: Undefined action %d\n",action);
-               break;
+               return ISD200_ERROR;
        }
 
        memcpy(srb->cmnd, &ata, sizeof(ata.generic));
@@ -525,8 +554,8 @@ static int isd200_read_regs( struct us_data *us )
                retStatus = ISD200_ERROR;
        } else {
                memcpy(info->ATARegs, info->RegsBuf, sizeof(info->ATARegs));
-               US_DEBUGP("   Got ATA Register[IDE_ERROR_OFFSET] = 0x%x\n", 
-                         info->ATARegs[IDE_ERROR_OFFSET]);
+               US_DEBUGP("   Got ATA Register[ATA_REG_ERROR_OFFSET] = 0x%x\n",
+                         info->ATARegs[ATA_REG_ERROR_OFFSET]);
        }
 
        return retStatus;
@@ -590,7 +619,7 @@ static void isd200_invoke_transport( struct us_data *us,
                return;
        }
 
-       if ((srb->resid > 0) &&
+       if ((scsi_get_resid(srb) > 0) &&
            !((srb->cmnd[0] == REQUEST_SENSE) ||
              (srb->cmnd[0] == INQUIRY) ||
              (srb->cmnd[0] == MODE_SENSE) ||
@@ -868,7 +897,7 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
                        break;
 
                if (!detect) {
-                       if (regs[IDE_STATUS_OFFSET] & BUSY_STAT ) {
+                       if (regs[ATA_REG_STATUS_OFFSET] & BUSY_STAT) {
                                US_DEBUGP("   %s status is still BSY, try again...\n",mstr);
                        } else {
                                US_DEBUGP("   %s status !BSY, continue with next operation\n",mstr);
@@ -878,12 +907,12 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
                /* check for BUSY_STAT and */
                /* WRERR_STAT (workaround ATA Zip drive) and */ 
                /* ERR_STAT (workaround for Archos CD-ROM) */
-               else if (regs[IDE_STATUS_OFFSET] & 
+               else if (regs[ATA_REG_STATUS_OFFSET] &
                         (BUSY_STAT | WRERR_STAT | ERR_STAT )) {
                        US_DEBUGP("   Status indicates it is not ready, try again...\n");
                }
                /* check for DRDY, ATA devices set DRDY after SRST */
-               else if (regs[IDE_STATUS_OFFSET] & READY_STAT) {
+               else if (regs[ATA_REG_STATUS_OFFSET] & READY_STAT) {
                        US_DEBUGP("   Identified ATA device\n");
                        info->DeviceFlags |= DF_ATA_DEVICE;
                        info->DeviceHead = master_slave;
@@ -892,8 +921,8 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
                /* check Cylinder High/Low to
                   determine if it is an ATAPI device
                */
-               else if ((regs[IDE_HCYL_OFFSET] == 0xEB) &&
-                        (regs[IDE_LCYL_OFFSET] == 0x14)) {
+               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
@@ -977,12 +1006,6 @@ static int isd200_manual_enum(struct us_data *us)
        return(retStatus);
 }
 
-/*
- *     We are the last non IDE user of the legacy IDE ident structures
- *     and we thus want to keep a private copy of this function so the
- *     driver can be used without the obsolete drivers/ide layer
- */
-
 static void isd200_fix_driveid (struct hd_driveid *id)
 {
 #ifndef __LITTLE_ENDIAN
@@ -1217,7 +1240,6 @@ static int isd200_get_inquiry_data( struct us_data *us )
        return(retStatus);
 }
 
-
 /**************************************************************************
  * isd200_scsi_to_ata
  *                                                                      
@@ -1266,7 +1288,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
                        ataCdb->generic.TransferBlockSize = 1;
                        ataCdb->generic.RegisterSelect = REG_COMMAND;
                        ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
-                       srb->request_bufflen = 0;
+                       isd200_srb_set_bufflen(srb, 0);
                } else {
                        US_DEBUGP("   Media Status not supported, just report okay\n");
                        srb->result = SAM_STAT_GOOD;
@@ -1284,7 +1306,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
                        ataCdb->generic.TransferBlockSize = 1;
                        ataCdb->generic.RegisterSelect = REG_COMMAND;
                        ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
-                       srb->request_bufflen = 0;
+                       isd200_srb_set_bufflen(srb, 0);
                } else {
                        US_DEBUGP("   Media Status not supported, just report okay\n");
                        srb->result = SAM_STAT_GOOD;
@@ -1390,7 +1412,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
                        ataCdb->generic.RegisterSelect = REG_COMMAND;
                        ataCdb->write.CommandByte = (srb->cmnd[4] & 0x1) ?
                                WIN_DOORLOCK : WIN_DOORUNLOCK;
-                       srb->request_bufflen = 0;
+                       isd200_srb_set_bufflen(srb, 0);
                } else {
                        US_DEBUGP("   Not removeable media, just report okay\n");
                        srb->result = SAM_STAT_GOOD;
@@ -1416,7 +1438,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
                        ataCdb->generic.TransferBlockSize = 1;
                        ataCdb->generic.RegisterSelect = REG_COMMAND;
                        ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
-                       srb->request_bufflen = 0;
+                       isd200_srb_set_bufflen(srb, 0);
                } else {
                        US_DEBUGP("   Nothing to do, just report okay\n");
                        srb->result = SAM_STAT_GOOD;
@@ -1525,7 +1547,7 @@ int isd200_Initialization(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;
 
        /* Make sure driver was initialized */
@@ -1533,11 +1555,14 @@ void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us)
        if (us->extra == NULL)
                US_DEBUGP("ERROR Driver not initialized\n");
 
-       /* Convert command */
-       srb->resid = 0;
+       scsi_set_resid(srb, 0);
+       /* scsi_bufflen might change in protocol translation to ata */
+       orig_bufflen = scsi_bufflen(srb);
        sendToTransport = isd200_scsi_to_ata(srb, us, &ataCdb);
 
        /* send the command to the transport layer */
        if (sendToTransport)
                isd200_invoke_transport(us, srb, &ataCdb);
+
+       isd200_srb_set_bufflen(srb, orig_bufflen);
 }