Merge /spare/repo/linux-2.6/
authorJeff Garzik <jgarzik@pobox.com>
Wed, 14 Sep 2005 12:57:30 +0000 (08:57 -0400)
committerJeff Garzik <jgarzik@pobox.com>
Wed, 14 Sep 2005 12:57:30 +0000 (08:57 -0400)
drivers/scsi/libata-core.c
drivers/scsi/libata-scsi.c
include/linux/ata.h
include/linux/libata.h

index 5cc53cd..62095bd 100644 (file)
@@ -62,6 +62,7 @@
 static unsigned int ata_busy_sleep (struct ata_port *ap,
                                    unsigned long tmout_pat,
                                    unsigned long tmout);
+static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev);
 static void ata_set_mode(struct ata_port *ap);
 static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev);
 static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift);
@@ -1131,7 +1132,7 @@ static inline void ata_dump_id(struct ata_device *dev)
 static void ata_dev_identify(struct ata_port *ap, unsigned int device)
 {
        struct ata_device *dev = &ap->device[device];
-       unsigned int i;
+       unsigned int major_version;
        u16 tmp;
        unsigned long xfer_modes;
        u8 status;
@@ -1229,9 +1230,9 @@ retry:
         * common ATA, ATAPI feature tests
         */
 
-       /* we require LBA and DMA support (bits 8 & 9 of word 49) */
-       if (!ata_id_has_dma(dev->id) || !ata_id_has_lba(dev->id)) {
-               printk(KERN_DEBUG "ata%u: no dma/lba\n", ap->id);
+       /* we require DMA support (bits 8 of word 49) */
+       if (!ata_id_has_dma(dev->id)) {
+               printk(KERN_DEBUG "ata%u: no dma\n", ap->id);
                goto err_out_nosup;
        }
 
@@ -1251,32 +1252,69 @@ retry:
                if (!ata_id_is_ata(dev->id))    /* sanity check */
                        goto err_out_nosup;
 
+               /* get major version */
                tmp = dev->id[ATA_ID_MAJOR_VER];
-               for (i = 14; i >= 1; i--)
-                       if (tmp & (1 << i))
+               for (major_version = 14; major_version >= 1; major_version--)
+                       if (tmp & (1 << major_version))
                                break;
 
-               /* we require at least ATA-3 */
-               if (i < 3) {
-                       printk(KERN_DEBUG "ata%u: no ATA-3\n", ap->id);
-                       goto err_out_nosup;
-               }
+               /*
+                * The exact sequence expected by certain pre-ATA4 drives is:
+                * SRST RESET
+                * IDENTIFY
+                * INITIALIZE DEVICE PARAMETERS
+                * anything else..
+                * Some drives were very specific about that exact sequence.
+                */
+               if (major_version < 4 || (!ata_id_has_lba(dev->id)))
+                       ata_dev_init_params(ap, dev);
+
+               if (ata_id_has_lba(dev->id)) {
+                       dev->flags |= ATA_DFLAG_LBA;
+
+                       if (ata_id_has_lba48(dev->id)) {
+                               dev->flags |= ATA_DFLAG_LBA48;
+                               dev->n_sectors = ata_id_u64(dev->id, 100);
+                       } else {
+                               dev->n_sectors = ata_id_u32(dev->id, 60);
+                       }
+
+                       /* print device info to dmesg */
+                       printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s\n",
+                              ap->id, device,
+                              major_version,
+                              ata_mode_string(xfer_modes),
+                              (unsigned long long)dev->n_sectors,
+                              dev->flags & ATA_DFLAG_LBA48 ? " LBA48" : " LBA");
+               } else { 
+                       /* CHS */
+
+                       /* Default translation */
+                       dev->cylinders  = dev->id[1];
+                       dev->heads      = dev->id[3];
+                       dev->sectors    = dev->id[6];
+                       dev->n_sectors  = dev->cylinders * dev->heads * dev->sectors;
+
+                       if (ata_id_current_chs_valid(dev->id)) {
+                               /* Current CHS translation is valid. */
+                               dev->cylinders = dev->id[54];
+                               dev->heads     = dev->id[55];
+                               dev->sectors   = dev->id[56];
+                               
+                               dev->n_sectors = ata_id_u32(dev->id, 57);
+                       }
+
+                       /* print device info to dmesg */
+                       printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors: CHS %d/%d/%d\n",
+                              ap->id, device,
+                              major_version,
+                              ata_mode_string(xfer_modes),
+                              (unsigned long long)dev->n_sectors,
+                              (int)dev->cylinders, (int)dev->heads, (int)dev->sectors);
 
-               if (ata_id_has_lba48(dev->id)) {
-                       dev->flags |= ATA_DFLAG_LBA48;
-                       dev->n_sectors = ata_id_u64(dev->id, 100);
-               } else {
-                       dev->n_sectors = ata_id_u32(dev->id, 60);
                }
 
                ap->host->max_cmd_len = 16;
-
-               /* print device info to dmesg */
-               printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu sectors:%s\n",
-                      ap->id, device,
-                      ata_mode_string(xfer_modes),
-                      (unsigned long long)dev->n_sectors,
-                      dev->flags & ATA_DFLAG_LBA48 ? " lba48" : "");
        }
 
        /* ATAPI-specific feature tests */
@@ -2143,6 +2181,54 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
        DPRINTK("EXIT\n");
 }
 
+/**
+ *     ata_dev_init_params - Issue INIT DEV PARAMS command
+ *     @ap: Port associated with device @dev
+ *     @dev: Device to which command will be sent
+ *
+ *     LOCKING:
+ */
+
+static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
+{
+       DECLARE_COMPLETION(wait);
+       struct ata_queued_cmd *qc;
+       int rc;
+       unsigned long flags;
+       u16 sectors = dev->id[6];
+       u16 heads   = dev->id[3];
+
+       /* Number of sectors per track 1-255. Number of heads 1-16 */
+       if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16)
+               return;
+
+       /* set up init dev params taskfile */
+       DPRINTK("init dev params \n");
+
+       qc = ata_qc_new_init(ap, dev);
+       BUG_ON(qc == NULL);
+
+       qc->tf.command = ATA_CMD_INIT_DEV_PARAMS;
+       qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+       qc->tf.protocol = ATA_PROT_NODATA;
+       qc->tf.nsect = sectors;
+       qc->tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
+
+       qc->waiting = &wait;
+       qc->complete_fn = ata_qc_complete_noop;
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       rc = ata_qc_issue(qc);
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+       if (rc)
+               ata_port_disable(ap);
+       else
+               wait_for_completion(&wait);
+
+       DPRINTK("EXIT\n");
+}
+
 /**
  *     ata_sg_clean - Unmap DMA memory associated with command
  *     @qc: Command containing DMA memory to be released
@@ -3147,8 +3233,12 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 
                ata_tf_init(ap, &qc->tf, dev->devno);
 
-               if (dev->flags & ATA_DFLAG_LBA48)
-                       qc->tf.flags |= ATA_TFLAG_LBA48;
+               if (dev->flags & ATA_DFLAG_LBA) {
+                       qc->tf.flags |= ATA_TFLAG_LBA;
+
+                       if (dev->flags & ATA_DFLAG_LBA48)
+                               qc->tf.flags |= ATA_TFLAG_LBA48;
+               }
        }
 
        return qc;
index 104fd9a..03b7a6d 100644 (file)
@@ -504,77 +504,107 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
 static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
 {
        struct ata_taskfile *tf = &qc->tf;
+       struct ata_device *dev = qc->dev;
+       unsigned int lba   = tf->flags & ATA_TFLAG_LBA;
        unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
        u64 dev_sectors = qc->dev->n_sectors;
-       u64 sect = 0;
-       u32 n_sect = 0;
+       u64 block = 0;
+       u32 n_block = 0;
 
        tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
        tf->protocol = ATA_PROT_NODATA;
-       tf->device |= ATA_LBA;
 
        if (scsicmd[0] == VERIFY) {
-               sect |= ((u64)scsicmd[2]) << 24;
-               sect |= ((u64)scsicmd[3]) << 16;
-               sect |= ((u64)scsicmd[4]) << 8;
-               sect |= ((u64)scsicmd[5]);
+               block |= ((u64)scsicmd[2]) << 24;
+               block |= ((u64)scsicmd[3]) << 16;
+               block |= ((u64)scsicmd[4]) << 8;
+               block |= ((u64)scsicmd[5]);
 
-               n_sect |= ((u32)scsicmd[7]) << 8;
-               n_sect |= ((u32)scsicmd[8]);
+               n_block |= ((u32)scsicmd[7]) << 8;
+               n_block |= ((u32)scsicmd[8]);
        }
 
        else if (scsicmd[0] == VERIFY_16) {
-               sect |= ((u64)scsicmd[2]) << 56;
-               sect |= ((u64)scsicmd[3]) << 48;
-               sect |= ((u64)scsicmd[4]) << 40;
-               sect |= ((u64)scsicmd[5]) << 32;
-               sect |= ((u64)scsicmd[6]) << 24;
-               sect |= ((u64)scsicmd[7]) << 16;
-               sect |= ((u64)scsicmd[8]) << 8;
-               sect |= ((u64)scsicmd[9]);
-
-               n_sect |= ((u32)scsicmd[10]) << 24;
-               n_sect |= ((u32)scsicmd[11]) << 16;
-               n_sect |= ((u32)scsicmd[12]) << 8;
-               n_sect |= ((u32)scsicmd[13]);
+               block |= ((u64)scsicmd[2]) << 56;
+               block |= ((u64)scsicmd[3]) << 48;
+               block |= ((u64)scsicmd[4]) << 40;
+               block |= ((u64)scsicmd[5]) << 32;
+               block |= ((u64)scsicmd[6]) << 24;
+               block |= ((u64)scsicmd[7]) << 16;
+               block |= ((u64)scsicmd[8]) << 8;
+               block |= ((u64)scsicmd[9]);
+
+               n_block |= ((u32)scsicmd[10]) << 24;
+               n_block |= ((u32)scsicmd[11]) << 16;
+               n_block |= ((u32)scsicmd[12]) << 8;
+               n_block |= ((u32)scsicmd[13]);
        }
 
        else
                return 1;
 
-       if (!n_sect)
+       if (!n_block)
                return 1;
-       if (sect >= dev_sectors)
+       if (block >= dev_sectors)
                return 1;
-       if ((sect + n_sect) > dev_sectors)
+       if ((block + n_block) > dev_sectors)
                return 1;
        if (lba48) {
-               if (n_sect > (64 * 1024))
+               if (n_block > (64 * 1024))
                        return 1;
        } else {
-               if (n_sect > 256)
+               if (n_block > 256)
                        return 1;
        }
 
-       if (lba48) {
-               tf->command = ATA_CMD_VERIFY_EXT;
+       if (lba) {
+               if (lba48) {
+                       tf->command = ATA_CMD_VERIFY_EXT;
 
-               tf->hob_nsect = (n_sect >> 8) & 0xff;
+                       tf->hob_nsect = (n_block >> 8) & 0xff;
 
-               tf->hob_lbah = (sect >> 40) & 0xff;
-               tf->hob_lbam = (sect >> 32) & 0xff;
-               tf->hob_lbal = (sect >> 24) & 0xff;
-       } else {
-               tf->command = ATA_CMD_VERIFY;
+                       tf->hob_lbah = (block >> 40) & 0xff;
+                       tf->hob_lbam = (block >> 32) & 0xff;
+                       tf->hob_lbal = (block >> 24) & 0xff;
+               } else {
+                       tf->command = ATA_CMD_VERIFY;
 
-               tf->device |= (sect >> 24) & 0xf;
-       }
+                       tf->device |= (block >> 24) & 0xf;
+               }
+
+               tf->nsect = n_block & 0xff;
 
-       tf->nsect = n_sect & 0xff;
+               tf->lbah = (block >> 16) & 0xff;
+               tf->lbam = (block >> 8) & 0xff;
+               tf->lbal = block & 0xff;
 
-       tf->lbah = (sect >> 16) & 0xff;
-       tf->lbam = (sect >> 8) & 0xff;
-       tf->lbal = sect & 0xff;
+               tf->device |= ATA_LBA;
+       } else {
+               /* CHS */
+               u32 sect, head, cyl, track;
+
+               /* Convert LBA to CHS */
+               track = (u32)block / dev->sectors;
+               cyl   = track / dev->heads;
+               head  = track % dev->heads;
+               sect  = (u32)block % dev->sectors + 1;
+
+               DPRINTK("block[%u] track[%u] cyl[%u] head[%u] sect[%u] \n", (u32)block, track, cyl, head, sect);
+               
+               /* Check whether the converted CHS can fit. 
+                  Cylinder: 0-65535 
+                  Head: 0-15
+                  Sector: 1-255*/
+               if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect)) 
+                       return 1;
+               
+               tf->command = ATA_CMD_VERIFY;
+               tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
+               tf->lbal = sect;
+               tf->lbam = cyl;
+               tf->lbah = cyl >> 8;
+               tf->device |= head;
+       }
 
        return 0;
 }
@@ -602,11 +632,14 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
 static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
 {
        struct ata_taskfile *tf = &qc->tf;
+       struct ata_device *dev = qc->dev;
+       unsigned int lba   = tf->flags & ATA_TFLAG_LBA;
        unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
+       u64 block = 0;
+       u32 n_block = 0;
 
        tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
        tf->protocol = qc->dev->xfer_protocol;
-       tf->device |= ATA_LBA;
 
        if (scsicmd[0] == READ_10 || scsicmd[0] == READ_6 ||
            scsicmd[0] == READ_16) {
@@ -616,90 +649,114 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
                tf->flags |= ATA_TFLAG_WRITE;
        }
 
+       /* Calculate the SCSI LBA and transfer length. */
        if (scsicmd[0] == READ_10 || scsicmd[0] == WRITE_10) {
-               if (lba48) {
-                       tf->hob_nsect = scsicmd[7];
-                       tf->hob_lbal = scsicmd[2];
+               block |= ((u64)scsicmd[2]) << 24;
+               block |= ((u64)scsicmd[3]) << 16;
+               block |= ((u64)scsicmd[4]) << 8;
+               block |= ((u64)scsicmd[5]);
 
-                       qc->nsect = ((unsigned int)scsicmd[7] << 8) |
-                                       scsicmd[8];
-               } else {
-                       /* if we don't support LBA48 addressing, the request
-                        * -may- be too large. */
-                       if ((scsicmd[2] & 0xf0) || scsicmd[7])
-                               return 1;
-
-                       /* stores LBA27:24 in lower 4 bits of device reg */
-                       tf->device |= scsicmd[2];
-
-                       qc->nsect = scsicmd[8];
-               }
-
-               tf->nsect = scsicmd[8];
-               tf->lbal = scsicmd[5];
-               tf->lbam = scsicmd[4];
-               tf->lbah = scsicmd[3];
+               n_block |= ((u32)scsicmd[7]) << 8;
+               n_block |= ((u32)scsicmd[8]);
 
                VPRINTK("ten-byte command\n");
-               if (qc->nsect == 0) /* we don't support length==0 cmds */
-                       return 1;
-               return 0;
-       }
-
-       if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
-               qc->nsect = tf->nsect = scsicmd[4];
-               if (!qc->nsect) {
-                       qc->nsect = 256;
-                       if (lba48)
-                               tf->hob_nsect = 1;
-               }
-
-               tf->lbal = scsicmd[3];
-               tf->lbam = scsicmd[2];
-               tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */
-
+       } else if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
+               block |= ((u64)scsicmd[2]) << 8;
+               block |= ((u64)scsicmd[3]);
+
+               n_block |= ((u32)scsicmd[4]);
+               if (!n_block)
+                       n_block = 256;
+       
                VPRINTK("six-byte command\n");
-               return 0;
+       } else if (scsicmd[0] == READ_16 || scsicmd[0] == WRITE_16) {
+               block |= ((u64)scsicmd[2]) << 56;
+               block |= ((u64)scsicmd[3]) << 48;
+               block |= ((u64)scsicmd[4]) << 40;
+               block |= ((u64)scsicmd[5]) << 32;
+               block |= ((u64)scsicmd[6]) << 24;
+               block |= ((u64)scsicmd[7]) << 16;
+               block |= ((u64)scsicmd[8]) << 8;
+               block |= ((u64)scsicmd[9]);
+
+               n_block |= ((u32)scsicmd[10]) << 24;
+               n_block |= ((u32)scsicmd[11]) << 16;
+               n_block |= ((u32)scsicmd[12]) << 8;
+               n_block |= ((u32)scsicmd[13]);
+
+               VPRINTK("sixteen-byte command\n");
+       } else {
+               DPRINTK("no-byte command\n");
+               return 1;
        }
 
-       if (scsicmd[0] == READ_16 || scsicmd[0] == WRITE_16) {
-               /* rule out impossible LBAs and sector counts */
-               if (scsicmd[2] || scsicmd[3] || scsicmd[10] || scsicmd[11])
-                       return 1;
+       /* Check and compose ATA command */
+       if (!n_block)
+               /* In ATA, sector count 0 means 256 or 65536 sectors, not 0 sectors. */
+               return 1;
 
+       if (lba) {
                if (lba48) {
-                       tf->hob_nsect = scsicmd[12];
-                       tf->hob_lbal = scsicmd[6];
-                       tf->hob_lbam = scsicmd[5];
-                       tf->hob_lbah = scsicmd[4];
-
-                       qc->nsect = ((unsigned int)scsicmd[12] << 8) |
-                                       scsicmd[13];
-               } else {
-                       /* once again, filter out impossible non-zero values */
-                       if (scsicmd[4] || scsicmd[5] || scsicmd[12] ||
-                           (scsicmd[6] & 0xf0))
+                       /* The request -may- be too large for LBA48. */
+                       if ((block >> 48) || (n_block > 65536))
                                return 1;
 
-                       /* stores LBA27:24 in lower 4 bits of device reg */
-                       tf->device |= scsicmd[6];
+                       tf->hob_nsect = (n_block >> 8) & 0xff;
+
+                       tf->hob_lbah = (block >> 40) & 0xff;
+                       tf->hob_lbam = (block >> 32) & 0xff;
+                       tf->hob_lbal = (block >> 24) & 0xff;
+               } else { 
+                       /* LBA28 */
+
+                       /* The request -may- be too large for LBA28. */
+                       if ((block >> 28) || (n_block > 256))
+                               return 1;
 
-                       qc->nsect = scsicmd[13];
+                       tf->device |= (block >> 24) & 0xf;
                }
+       
+               qc->nsect = n_block;
+               tf->nsect = n_block & 0xff;
 
-               tf->nsect = scsicmd[13];
-               tf->lbal = scsicmd[9];
-               tf->lbam = scsicmd[8];
-               tf->lbah = scsicmd[7];
+               tf->lbah = (block >> 16) & 0xff;
+               tf->lbam = (block >> 8) & 0xff;
+               tf->lbal = block & 0xff;
 
-               VPRINTK("sixteen-byte command\n");
-               if (qc->nsect == 0) /* we don't support length==0 cmds */
+               tf->device |= ATA_LBA;
+       } else { 
+               /* CHS */
+               u32 sect, head, cyl, track;
+
+               /* The request -may- be too large for CHS addressing. */
+               if ((block >> 28) || (n_block > 256))
                        return 1;
-               return 0;
+                       
+               /* Convert LBA to CHS */
+               track = (u32)block / dev->sectors;
+               cyl   = track / dev->heads;
+               head  = track % dev->heads;
+               sect  = (u32)block % dev->sectors + 1;
+
+               DPRINTK("block[%u] track[%u] cyl[%u] head[%u] sect[%u] \n", 
+                       (u32)block, track, cyl, head, sect);
+               
+               /* Check whether the converted CHS can fit. 
+                  Cylinder: 0-65535 
+                  Head: 0-15
+                  Sector: 1-255*/
+               if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect)) 
+                       return 1;
+               
+               qc->nsect = n_block;
+               tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
+               tf->lbal = sect;
+               tf->lbam = cyl;
+               tf->lbah = cyl >> 8;
+               tf->device |= head;
        }
 
-       DPRINTK("no-byte command\n");
-       return 1;
+       return 0;
 }
 
 static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
@@ -1246,10 +1303,20 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
 
        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);
+       if (ata_id_has_lba(args->id)) {
+               if (ata_id_has_lba48(args->id))
+                       n_sectors = ata_id_u64(args->id, 100);
+               else
+                       n_sectors = ata_id_u32(args->id, 60);
+       } else {
+               /* CHS default translation */
+               n_sectors = args->id[1] * args->id[3] * args->id[6];
+
+               if (ata_id_current_chs_valid(args->id))
+                       /* CHS current translation */
+                       n_sectors = ata_id_u32(args->id, 57);
+       }
+
        n_sectors--;            /* ATA TotalUserSectors - 1 */
 
        if (args->cmd->cmnd[0] == READ_CAPACITY) {
index a5b74ef..85169ea 100644 (file)
@@ -132,6 +132,7 @@ enum {
        ATA_CMD_PACKET          = 0xA0,
        ATA_CMD_VERIFY          = 0x40,
        ATA_CMD_VERIFY_EXT      = 0x42,
+       ATA_CMD_INIT_DEV_PARAMS = 0x91,
 
        /* SETFEATURES stuff */
        SETFEATURES_XFER        = 0x03,
@@ -181,6 +182,7 @@ enum {
        ATA_TFLAG_ISADDR        = (1 << 1), /* enable r/w to nsect/lba regs */
        ATA_TFLAG_DEVICE        = (1 << 2), /* enable r/w to device reg */
        ATA_TFLAG_WRITE         = (1 << 3), /* data dir: host->dev==1 (write) */
+       ATA_TFLAG_LBA           = (1 << 4), /* enable LBA */
 };
 
 enum ata_tf_protocols {
@@ -250,6 +252,18 @@ struct ata_taskfile {
          ((u64) (id)[(n) + 1] << 16) | \
          ((u64) (id)[(n) + 0]) )
 
+static inline int ata_id_current_chs_valid(u16 *id)
+{
+       /* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command 
+          has not been issued to the device then the values of 
+          id[54] to id[56] are vendor specific. */
+       return (id[53] & 0x01) && /* Current translation valid */
+               id[54] &&  /* cylinders in current translation */
+               id[55] &&  /* heads in current translation */
+               id[55] <= 16 &&
+               id[56];    /* sectors in current translation */
+}
+
 static inline int atapi_cdb_len(u16 *dev_id)
 {
        u16 tmp = dev_id[0] & 0x3;
index 022105c..f76f54a 100644 (file)
@@ -97,6 +97,7 @@ enum {
        ATA_DFLAG_LBA48         = (1 << 0), /* device supports LBA48 */
        ATA_DFLAG_PIO           = (1 << 1), /* device currently in PIO mode */
        ATA_DFLAG_LOCK_SECTORS  = (1 << 2), /* don't adjust max_sectors */
+       ATA_DFLAG_LBA           = (1 << 3), /* device supports LBA */
 
        ATA_DEV_UNKNOWN         = 0,    /* unknown device */
        ATA_DEV_ATA             = 1,    /* ATA device */
@@ -282,6 +283,11 @@ struct ata_device {
        u8                      xfer_protocol;  /* taskfile xfer protocol */
        u8                      read_cmd;       /* opcode to use on read */
        u8                      write_cmd;      /* opcode to use on write */
+
+       /* for CHS addressing */
+       u16                     cylinders;      /* Number of cylinders */
+       u16                     heads;          /* Number of heads */
+       u16                     sectors;        /* Number of sectors per track */
 };
 
 struct ata_port {