vserver 1.9.5.x5
[linux-2.6.git] / drivers / scsi / libata-scsi.c
index 47c0af2..7f59ef6 100644 (file)
@@ -34,9 +34,6 @@
 #include "libata.h"
 
 typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, u8 *scsicmd);
-static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
-                             struct scsi_cmnd *cmd,
-                             void (*done)(struct scsi_cmnd *));
 static struct ata_device *
 ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev);
 
@@ -100,7 +97,7 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
                return 0;
 
        default:
-               rc = -EOPNOTSUPP;
+               rc = -ENOTTY;
                break;
        }
 
@@ -159,6 +156,7 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap,
 /**
  *     ata_to_sense_error - convert ATA error to SCSI error
  *     @qc: Command that we are erroring out
+ *     @drv_stat: value contained in ATA status register
  *
  *     Converts an ATA error into a SCSI error. While we are at it
  *     we decode and dump the ATA error for the user so that they
@@ -204,7 +202,7 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
                {0x40,          MEDIUM_ERROR, 0x11, 0x04},      // Uncorrectable ECC error      Unrecovered read error
                /* BBD - block marked bad */
                {0x80,          MEDIUM_ERROR, 0x11, 0x04},      // Block marked bad               Medium error, unrecovered read error
-               {0xFF, 0xFF, 0xFF, 0xFF}, // END mark 
+               {0xFF, 0xFF, 0xFF, 0xFF}, // END mark
        };
        static unsigned char stat_table[][4] = {
                /* Must be first because BUSY means no other bits valid */
@@ -212,22 +210,22 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
                {0x20,          HARDWARE_ERROR,  0x00, 0x00},   // Device fault
                {0x08,          ABORTED_COMMAND, 0x47, 0x00},   // Timed out in xfer, fake parity for now
                {0x04,          RECOVERED_ERROR, 0x11, 0x00},   // Recovered ECC error    Medium error, recovered
-               {0xFF, 0xFF, 0xFF, 0xFF}, // END mark 
+               {0xFF, 0xFF, 0xFF, 0xFF}, // END mark
        };
        int i = 0;
 
        cmd->result = SAM_STAT_CHECK_CONDITION;
-       
+
        /*
         *      Is this an error we can process/parse
         */
-        
+
        if(drv_stat & ATA_ERR)
                /* Read the err bits */
                err = ata_chk_err(qc->ap);
 
        /* Display the ATA level error info */
-       
+
        printk(KERN_WARNING "ata%u: status=0x%02x { ", qc->ap->id, drv_stat);
        if(drv_stat & 0x80)
        {
@@ -244,7 +242,7 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
                if(drv_stat & 0x01)     printk("Error ");
        }
        printk("}\n");
-       
+
        if(err)
        {
                printk(KERN_WARNING "ata%u: error=0x%02x { ", qc->ap->id, err);
@@ -261,11 +259,11 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
                if(err & 0x02)          printk("TrackZeroNotFound ");
                if(err & 0x01)          printk("AddrMarkNotFound ");
                printk("}\n");
-               
+
                /* Should we dump sector info here too ?? */
        }
-               
-       
+
+
        /* Look for err */
        while(sense_table[i][0] != 0xFF)
        {
@@ -284,7 +282,8 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
        /* No immediate match */
        if(err)
                printk(KERN_DEBUG "ata%u: no sense translation for 0x%02x\n", qc->ap->id, err);
-       
+
+       i = 0;
        /* Fall back to interpreting status bits */
        while(stat_table[i][0] != 0xFF)
        {
@@ -302,7 +301,7 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
        /* No error ?? */
        printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat);
        /* additional-sense-code[-qualifier] */
-       
+
        sb[0] = 0x70;
        sb[2] = MEDIUM_ERROR;
        sb[7] = 0x0A;
@@ -411,7 +410,7 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
        tf->protocol = ATA_PROT_NODATA;
 
        if ((tf->flags & ATA_TFLAG_LBA48) &&
-           (ata_id_has_flush_ext(qc->dev)))
+           (ata_id_has_flush_ext(qc->dev->id)))
                tf->command = ATA_CMD_FLUSH_EXT;
        else
                tf->command = ATA_CMD_FLUSH;
@@ -489,19 +488,24 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
        }
 
        if (lba48) {
+               tf->command = ATA_CMD_VERIFY_EXT;
+
                tf->hob_nsect = (n_sect >> 8) & 0xff;
 
                tf->hob_lbah = (sect >> 40) & 0xff;
                tf->hob_lbam = (sect >> 32) & 0xff;
                tf->hob_lbal = (sect >> 24) & 0xff;
-       } else
+       } else {
+               tf->command = ATA_CMD_VERIFY;
+
                tf->device |= (sect >> 24) & 0xf;
+       }
 
        tf->nsect = n_sect & 0xff;
 
-       tf->hob_lbah = (sect >> 16) & 0xff;
-       tf->hob_lbam = (sect >> 8) & 0xff;
-       tf->hob_lbal = sect & 0xff;
+       tf->lbah = (sect >> 16) & 0xff;
+       tf->lbam = (sect >> 8) & 0xff;
+       tf->lbal = sect & 0xff;
 
        return 0;
 }
@@ -601,7 +605,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
                                return 1;
 
                        /* stores LBA27:24 in lower 4 bits of device reg */
-                       tf->device |= scsicmd[2];
+                       tf->device |= scsicmd[6];
 
                        qc->nsect = scsicmd[13];
                }
@@ -681,7 +685,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
                        ata_sg_init_one(qc, cmd->request_buffer,
                                        cmd->request_bufflen);
 
-               qc->pci_dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
+               qc->dma_dir = cmd->sc_data_direction;
        }
 
        qc->complete_fn = ata_scsi_qc_complete;
@@ -697,6 +701,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
        return;
 
 err_out:
+       ata_qc_free(qc);
        ata_bad_cdb(cmd, done);
        DPRINTK("EXIT - badcmd\n");
 }
@@ -731,7 +736,6 @@ static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out)
                buflen = cmd->request_bufflen;
        }
 
-       memset(buf, 0, buflen);
        *buf_out = buf;
        return buflen;
 }
@@ -739,6 +743,7 @@ static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out)
 /**
  *     ata_scsi_rbuf_put - Unmap response buffer.
  *     @cmd: SCSI command containing buffer to be unmapped.
+ *     @buf: buffer to unmap
  *
  *     Unmaps response buffer contained within @cmd.
  *
@@ -746,19 +751,19 @@ static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out)
  *     spin_lock_irqsave(host_set lock)
  */
 
-static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd)
+static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
 {
        if (cmd->use_sg) {
                struct scatterlist *sg;
 
                sg = (struct scatterlist *) cmd->request_buffer;
-               kunmap_atomic(sg->page, KM_USER0);
+               kunmap_atomic(buf - sg->offset, KM_USER0);
        }
 }
 
 /**
  *     ata_scsi_rbuf_fill - wrapper for SCSI command simulators
- *     @args: Port / device / SCSI command of interest.
+ *     @args: device IDENTIFY data / SCSI command of interest.
  *     @actor: Callback hook for desired SCSI command simulator
  *
  *     Takes care of the hard work of simulating a SCSI command...
@@ -780,8 +785,9 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
        struct scsi_cmnd *cmd = args->cmd;
 
        buflen = ata_scsi_rbuf_get(cmd, &rbuf);
+       memset(rbuf, 0, buflen);
        rc = actor(args, rbuf, buflen);
-       ata_scsi_rbuf_put(cmd);
+       ata_scsi_rbuf_put(cmd, rbuf);
 
        if (rc)
                ata_bad_cdb(cmd, args->done);
@@ -793,7 +799,7 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
 
 /**
  *     ata_scsiop_inq_std - Simulate INQUIRY command
- *     @args: Port / device / SCSI command of interest.
+ *     @args: device IDENTIFY data / SCSI command of interest.
  *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
  *     @buflen: Response buffer length.
  *
@@ -807,8 +813,6 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
 unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
                               unsigned int buflen)
 {
-       struct ata_device *dev = args->dev;
-
        u8 hdr[] = {
                TYPE_DISK,
                0,
@@ -818,7 +822,7 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
        };
 
        /* set scsi removeable (RMB) bit per ata bit */
-       if (ata_id_removeable(dev))
+       if (ata_id_removeable(args->id))
                hdr[1] |= (1 << 7);
 
        VPRINTK("ENTER\n");
@@ -827,8 +831,8 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
 
        if (buflen > 35) {
                memcpy(&rbuf[8], "ATA     ", 8);
-               ata_dev_id_string(dev, &rbuf[16], ATA_ID_PROD_OFS, 16);
-               ata_dev_id_string(dev, &rbuf[32], ATA_ID_FW_REV_OFS, 4);
+               ata_dev_id_string(args->id, &rbuf[16], ATA_ID_PROD_OFS, 16);
+               ata_dev_id_string(args->id, &rbuf[32], ATA_ID_FW_REV_OFS, 4);
                if (rbuf[32] == 0 || rbuf[32] == ' ')
                        memcpy(&rbuf[32], "n/a ", 4);
        }
@@ -852,7 +856,7 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
 
 /**
  *     ata_scsiop_inq_00 - Simulate INQUIRY EVPD page 0, list of pages
- *     @args: Port / device / SCSI command of interest.
+ *     @args: device IDENTIFY data / SCSI command of interest.
  *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
  *     @buflen: Response buffer length.
  *
@@ -880,7 +884,7 @@ unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
 
 /**
  *     ata_scsiop_inq_80 - Simulate INQUIRY EVPD page 80, device serial number
- *     @args: Port / device / SCSI command of interest.
+ *     @args: device IDENTIFY data / SCSI command of interest.
  *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
  *     @buflen: Response buffer length.
  *
@@ -901,8 +905,8 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
        };
        memcpy(rbuf, hdr, sizeof(hdr));
 
-       if (buflen > (ATA_SERNO_LEN + 4))
-               ata_dev_id_string(args->dev, (unsigned char *) &rbuf[4],
+       if (buflen > (ATA_SERNO_LEN + 4 - 1))
+               ata_dev_id_string(args->id, (unsigned char *) &rbuf[4],
                                  ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
 
        return 0;
@@ -912,7 +916,7 @@ static const char *inq_83_str = "Linux ATA-SCSI simulator";
 
 /**
  *     ata_scsiop_inq_83 - Simulate INQUIRY EVPD page 83, device identity
- *     @args: Port / device / SCSI command of interest.
+ *     @args: device IDENTIFY data / SCSI command of interest.
  *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
  *     @buflen: Response buffer length.
  *
@@ -930,7 +934,7 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
        rbuf[3] = 4 + strlen(inq_83_str);       /* page len */
 
        /* our one and only identification descriptor (vendor-specific) */
-       if (buflen > (strlen(inq_83_str) + 4 + 4)) {
+       if (buflen > (strlen(inq_83_str) + 4 + 4 - 1)) {
                rbuf[4 + 0] = 2;        /* code set: ASCII */
                rbuf[4 + 3] = strlen(inq_83_str);
                memcpy(rbuf + 4 + 4, inq_83_str, strlen(inq_83_str));
@@ -941,7 +945,7 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
 
 /**
  *     ata_scsiop_noop -
- *     @args: Port / device / SCSI command of interest.
+ *     @args: device IDENTIFY data / SCSI command of interest.
  *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
  *     @buflen: Response buffer length.
  *
@@ -989,7 +993,7 @@ static void ata_msense_push(u8 **ptr_io, const u8 *last,
 
 /**
  *     ata_msense_caching - Simulate MODE SENSE caching info page
- *     @dev: Device associated with this MODE SENSE command
+ *     @id: device IDENTIFY data
  *     @ptr_io: (input/output) Location to store more output data
  *     @last: End of output data buffer
  *
@@ -1001,7 +1005,7 @@ static void ata_msense_push(u8 **ptr_io, const u8 *last,
  *     None.
  */
 
-static unsigned int ata_msense_caching(struct ata_device *dev, u8 **ptr_io,
+static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io,
                                       const u8 *last)
 {
        u8 page[] = {
@@ -1011,9 +1015,9 @@ static unsigned int ata_msense_caching(struct ata_device *dev, u8 **ptr_io,
                0, 0, 0, 0, 0, 0, 0, 0          /* 8 zeroes */
        };
 
-       if (ata_id_wcache_enabled(dev))
+       if (ata_id_wcache_enabled(id))
                page[2] |= (1 << 2);    /* write cache enable */
-       if (!ata_id_rahead_enabled(dev))
+       if (!ata_id_rahead_enabled(id))
                page[12] |= (1 << 5);   /* disable read ahead */
 
        ata_msense_push(ptr_io, last, page, sizeof(page));
@@ -1067,7 +1071,7 @@ static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
 
 /**
  *     ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands
- *     @args: Port / device / SCSI command of interest.
+ *     @args: device IDENTIFY data / SCSI command of interest.
  *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
  *     @buflen: Response buffer length.
  *
@@ -1081,7 +1085,6 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
                                  unsigned int buflen)
 {
        u8 *scsicmd = args->cmd->cmnd, *p, *last;
-       struct ata_device *dev = args->dev;
        unsigned int page_control, six_byte, output_len;
 
        VPRINTK("ENTER\n");
@@ -1109,7 +1112,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
                break;
 
        case 0x08:              /* caching */
-               output_len += ata_msense_caching(dev, &p, last);
+               output_len += ata_msense_caching(args->id, &p, last);
                break;
 
        case 0x0a: {            /* control mode */
@@ -1119,7 +1122,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
 
        case 0x3f:              /* all pages */
                output_len += ata_msense_rw_recovery(&p, last);
-               output_len += ata_msense_caching(dev, &p, last);
+               output_len += ata_msense_caching(args->id, &p, last);
                output_len += ata_msense_ctl_mode(&p, last);
                break;
 
@@ -1141,7 +1144,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
 
 /**
  *     ata_scsiop_read_cap - Simulate READ CAPACITY[ 16] commands
- *     @args: Port / device / SCSI command of interest.
+ *     @args: device IDENTIFY data / SCSI command of interest.
  *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
  *     @buflen: Response buffer length.
  *
@@ -1154,11 +1157,15 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
 unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
                                unsigned int buflen)
 {
-       u64 n_sectors = args->dev->n_sectors;
+       u64 n_sectors;
        u32 tmp;
 
        VPRINTK("ENTER\n");
 
+       if (ata_id_has_lba48(args->id))
+               n_sectors = ata_id_u64(args->id, 100);
+       else
+               n_sectors = ata_id_u32(args->id, 60);
        n_sectors--;            /* ATA TotalUserSectors - 1 */
 
        tmp = n_sectors;        /* note: truncates, if lba48 */
@@ -1196,7 +1203,7 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
 
 /**
  *     ata_scsiop_report_luns - Simulate REPORT LUNS command
- *     @args: Port / device / SCSI command of interest.
+ *     @args: device IDENTIFY data / SCSI command of interest.
  *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
  *     @buflen: Response buffer length.
  *
@@ -1248,9 +1255,15 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
 {
        struct scsi_cmnd *cmd = qc->scsicmd;
 
-       if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ)))
+       if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) {
+               DPRINTK("request check condition\n");
+
                cmd->result = SAM_STAT_CHECK_CONDITION;
-       else {
+
+               qc->scsidone(cmd);
+
+               return 1;
+       } else {
                u8 *scsicmd = cmd->cmnd;
 
                if (scsicmd[0] == INQUIRY) {
@@ -1260,7 +1273,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
                        buflen = ata_scsi_rbuf_get(cmd, &buf);
                        buf[2] = 0x5;
                        buf[3] = (buf[3] & 0xf0) | 2;
-                       ata_scsi_rbuf_put(cmd);
+                       ata_scsi_rbuf_put(cmd, buf);
                }
                cmd->result = SAM_STAT_GOOD;
        }
@@ -1288,6 +1301,11 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
        int using_pio = (dev->flags & ATA_DFLAG_PIO);
        int nodata = (cmd->sc_data_direction == SCSI_DATA_NONE);
 
+       if (!using_pio)
+               /* Check whether ATAPI DMA is safe */
+               if (ata_check_atapi_dma(qc))
+                       using_pio = 1;
+
        memcpy(&qc->cdb, scsicmd, qc->ap->cdb_len);
 
        qc->complete_fn = atapi_qc_complete;
@@ -1322,13 +1340,15 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
 #endif
        }
 
+       qc->nbytes = cmd->bufflen;
+
        return 0;
 }
 
 /**
  *     ata_scsi_find_dev - lookup ata_device from scsi_cmnd
  *     @ap: ATA port to which the device is attached
- *     @cmd: SCSI command to be sent to the device
+ *     @scsidev: SCSI device from which we derive the ATA device
  *
  *     Given various information provided in struct scsi_cmnd,
  *     map that onto an ATA bus, and using that mapping
@@ -1472,7 +1492,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
                if (xlat_func)
                        ata_scsi_translate(ap, dev, cmd, done, xlat_func);
                else
-                       ata_scsi_simulate(ap, dev, cmd, done);
+                       ata_scsi_simulate(dev->id, cmd, done);
        } else
                ata_scsi_translate(ap, dev, cmd, done, atapi_xlat);
 
@@ -1482,8 +1502,7 @@ out_unlock:
 
 /**
  *     ata_scsi_simulate - simulate SCSI command on ATA device
- *     @ap: Port to which ATA device is attached.
- *     @dev: Target device for CDB.
+ *     @id: current IDENTIFY data for target device.
  *     @cmd: SCSI command being sent to device.
  *     @done: SCSI command completion function.
  *
@@ -1494,15 +1513,14 @@ out_unlock:
  *     spin_lock_irqsave(host_set lock)
  */
 
-static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
-                             struct scsi_cmnd *cmd,
-                             void (*done)(struct scsi_cmnd *))
+void ata_scsi_simulate(u16 *id,
+                     struct scsi_cmnd *cmd,
+                     void (*done)(struct scsi_cmnd *))
 {
        struct ata_scsi_args args;
        u8 *scsicmd = cmd->cmnd;
 
-       args.ap = ap;
-       args.dev = dev;
+       args.id = id;
        args.cmd = cmd;
        args.done = done;