Merge branch 'upstream'
authorJeff Garzik <jgarzik@pobox.com>
Sun, 9 Oct 2005 14:40:44 +0000 (10:40 -0400)
committerJeff Garzik <jgarzik@pobox.com>
Sun, 9 Oct 2005 14:40:44 +0000 (10:40 -0400)
1  2 
drivers/scsi/libata-scsi.c
drivers/scsi/libata.h

index 1b00bc618e157ab02c5902399bb6e39b8fef4cb6,c64169ca7ff0b0a61e00da65599625ed0bc7f871..698203bf4f69279b433cca223406e407f0139ed6
@@@ -381,10 -185,11 +389,11 @@@ void ata_dump_status(unsigned id, struc
   *    LOCKING:
   *    spin_lock_irqsave(host_set lock)
   */
 -
 -void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
 +void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, 
 +                      u8 *ascq)
  {
 -      struct scsi_cmnd *cmd = qc->scsicmd;
 -      u8 err = 0;
 +      int i;
++
        /* Based on the 3ware driver translation table */
        static unsigned char sense_table[][4] = {
                /* BBD|ECC|ID|MAR */
        /*
         *      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)
 -      {
 -              printk("Busy ");
 -              err = 0;        /* Data is not valid in this case */
 +      if (drv_stat & ATA_BUSY) {
 +              drv_err = 0;    /* Ignore the err bits, they're invalid */
        }
 -      else {
 -              if(drv_stat & 0x40)     printk("DriveReady ");
 -              if(drv_stat & 0x20)     printk("DeviceFault ");
 -              if(drv_stat & 0x10)     printk("SeekComplete ");
 -              if(drv_stat & 0x08)     printk("DataRequest ");
 -              if(drv_stat & 0x04)     printk("CorrectedError ");
 -              if(drv_stat & 0x02)     printk("Index ");
 -              if(drv_stat & 0x01)     printk("Error ");
 +
 +      if (drv_err) {
 +              /* Look for drv_err */
 +              for (i = 0; sense_table[i][0] != 0xFF; i++) {
 +                      /* Look for best matches first */
 +                      if ((sense_table[i][0] & drv_err) == 
 +                          sense_table[i][0]) {
 +                              *sk = sense_table[i][1];
 +                              *asc = sense_table[i][2];
 +                              *ascq = sense_table[i][3];
 +                              goto translate_done;
 +                      }
 +              }
 +              /* No immediate match */
 +              printk(KERN_WARNING "ata%u: no sense translation for "
 +                     "error 0x%02x\n", id, drv_err);
        }
 -      printk("}\n");
 -
 -      if(err)
 -      {
 -              printk(KERN_WARNING "ata%u: error=0x%02x { ", qc->ap->id, err);
 -              if(err & 0x04)          printk("DriveStatusError ");
 -              if(err & 0x80)
 -              {
 -                      if(err & 0x04)
 -                              printk("BadCRC ");
 -                      else
 -                              printk("Sector ");
 +
 +      /* Fall back to interpreting status bits */
 +      for (i = 0; stat_table[i][0] != 0xFF; i++) {
 +              if (stat_table[i][0] & drv_stat) {
 +                      *sk = stat_table[i][1];
 +                      *asc = stat_table[i][2];
 +                      *ascq = stat_table[i][3];
 +                      goto translate_done;
                }
 -              if(err & 0x40)          printk("UncorrectableError ");
 -              if(err & 0x10)          printk("SectorIdNotFound ");
 -              if(err & 0x02)          printk("TrackZeroNotFound ");
 -              if(err & 0x01)          printk("AddrMarkNotFound ");
 -              printk("}\n");
 +      }
 +      /* No error?  Undecoded? */
 +      printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n", 
 +             id, drv_stat);
 +
 +      /* For our last chance pick, use medium read error because
 +       * it's much more common than an ATA drive telling you a write
 +       * has failed.
 +       */
 +      *sk = MEDIUM_ERROR;
 +      *asc = 0x11; /* "unrecovered read error" */
 +      *ascq = 0x04; /*  "auto-reallocation failed" */
 +
 + translate_done:
 +      printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x to "
 +             "SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n", id, drv_stat, drv_err,
 +             *sk, *asc, *ascq);
 +      return;
 +}
 +
 +/*
 + *    ata_gen_ata_desc_sense - Generate check condition sense block.
 + *    @qc: Command that completed.
 + *
 + *    This function is specific to the ATA descriptor format sense
 + *    block specified for the ATA pass through commands.  Regardless
 + *    of whether the command errored or not, return a sense
 + *    block. Copy all controller registers into the sense
 + *    block. Clear sense key, ASC & ASCQ if there is no error.
 + *
 + *    LOCKING:
 + *    spin_lock_irqsave(host_set lock)
 + */
 +void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
 +{
 +      struct scsi_cmnd *cmd = qc->scsicmd;
 +      struct ata_taskfile *tf = &qc->tf;
 +      unsigned char *sb = cmd->sense_buffer;
 +      unsigned char *desc = sb + 8;
 +
 +      memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
 +
 +      cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
 +
 +      /*
 +       * Read the controller registers.
 +       */
 +      assert(NULL != qc->ap->ops->tf_read);
 +      qc->ap->ops->tf_read(qc->ap, tf);
  
 -              /* Should we dump sector info here too ?? */
 +      /*
 +       * Use ata_to_sense_error() to map status register bits
 +       * onto sense key, asc & ascq.
 +       */
 +      if (unlikely(tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) {
 +              ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
 +                                 &sb[1], &sb[2], &sb[3]);
 +              sb[1] &= 0x0f;
        }
  
 +      /*
 +       * Sense data is current and format is descriptor.
 +       */
 +      sb[0] = 0x72;
  
 -      /* Look for err */
 -      while(sense_table[i][0] != 0xFF)
 -      {
 -              /* Look for best matches first */
 -              if((sense_table[i][0] & err) == sense_table[i][0])
 -              {
 -                      ata_scsi_set_sense(cmd, sense_table[i][1] /* sk */,
 -                                         sense_table[i][2] /* asc */,
 -                                         sense_table[i][3] /* ascq */ );
 -                      return;
 -              }
 -              i++;
 +      desc[0] = 0x09;
 +
 +      /*
 +       * Set length of additional sense data.
 +       * Since we only populate descriptor 0, the total
 +       * length is the same (fixed) length as descriptor 0.
 +       */
 +      desc[1] = sb[7] = 14;
 +
 +      /*
 +       * Copy registers into sense buffer.
 +       */
 +      desc[2] = 0x00;
 +      desc[3] = tf->feature;  /* == error reg */
 +      desc[5] = tf->nsect;
 +      desc[7] = tf->lbal;
 +      desc[9] = tf->lbam;
 +      desc[11] = tf->lbah;
 +      desc[12] = tf->device;
 +      desc[13] = tf->command; /* == status reg */
 +
 +      /*
 +       * Fill in Extend bit, and the high order bytes
 +       * if applicable.
 +       */
 +      if (tf->flags & ATA_TFLAG_LBA48) {
 +              desc[2] |= 0x01;
 +              desc[4] = tf->hob_nsect;
 +              desc[6] = tf->hob_lbal;
 +              desc[8] = tf->hob_lbam;
 +              desc[10] = tf->hob_lbah;
        }
 -      /* 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)
 -      {
 -              if(stat_table[i][0] & drv_stat)
 -              {
 -                      ata_scsi_set_sense(cmd, sense_table[i][1] /* sk */,
 -                                         sense_table[i][2] /* asc */,
 -                                         sense_table[i][3] /* ascq */ );
 -                      return;
 -              }
 -              i++;
 +/**
 + *    ata_gen_fixed_sense - generate a SCSI fixed sense block
 + *    @qc: Command that we are erroring out
 + *
 + *    Leverage ata_to_sense_error() to give us the codes.  Fit our
 + *    LBA in here if there's room.
 + *
 + *    LOCKING:
 + *    inherited from caller
 + */
 +void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
 +{
 +      struct scsi_cmnd *cmd = qc->scsicmd;
 +      struct ata_taskfile *tf = &qc->tf;
 +      unsigned char *sb = cmd->sense_buffer;
 +
 +      memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
 +
 +      cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
 +
 +      /*
 +       * Read the controller registers.
 +       */
 +      assert(NULL != qc->ap->ops->tf_read);
 +      qc->ap->ops->tf_read(qc->ap, tf);
 +
 +      /*
 +       * Use ata_to_sense_error() to map status register bits
 +       * onto sense key, asc & ascq.
 +       */
 +      if (unlikely(tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) {
 +              ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
 +                                 &sb[2], &sb[12], &sb[13]);
 +              sb[2] &= 0x0f;
        }
 -      /* No error ?? */
 -      printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat);
 -      /* additional-sense-code[-qualifier] */
  
 -      if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
 -              ata_scsi_set_sense(cmd, MEDIUM_ERROR, 0x11, 0x4);
 -              /* "unrecovered read error" */
 -      } else {
 -              ata_scsi_set_sense(cmd, MEDIUM_ERROR, 0xc, 0x2);
 -              /* "write error - auto-reallocation failed" */
 +      sb[0] = 0x70;
 +      sb[7] = 0x0a;
 +
- #if 0 /* when C/H/S support is merged */
 +      if (tf->flags & ATA_TFLAG_LBA && !(tf->flags & ATA_TFLAG_LBA48)) {
- #endif
-       if (!(tf->flags & ATA_TFLAG_LBA48)) {
 +              /* A small (28b) LBA will fit in the 32b info field */
 +              sb[0] |= 0x80;          /* set valid bit */
 +              sb[3] = tf->device & 0x0f;
 +              sb[4] = tf->lbah;
 +              sb[5] = tf->lbam;
 +              sb[6] = tf->lbal;
        }
  }
  
index 0f1db892f6aab86226e63ba9b5c4df5046546a76,a18f2ac1d4a132484a274436c1631f209fda4ac8..9d951a2909cebb7bd41723a864e61b5650d95e1b
@@@ -53,6 -52,10 +54,9 @@@ extern int ata_cmd_ioctl(struct scsi_de
  
  
  /* libata-scsi.c */
 -extern void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat);
+ extern void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
+                        struct scsi_cmnd *cmd);
+ extern void ata_scsi_scan_host(struct ata_port *ap);
  extern int ata_scsi_error(struct Scsi_Host *host);
  extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
                               unsigned int buflen);