--- libata-dev-2.6/drivers/scsi/libata-scsi.c 2005-02-14 17:18:22.000000000 +0800 +++ libata-dev-2.6-mod/drivers/scsi/libata-scsi.c 2005-02-14 17:25:43.000000000 +0800 @@ -689,6 +689,8 @@ 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 block = 0; @@ -696,7 +698,6 @@ tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf->protocol = ATA_PROT_NODATA; - tf->device |= ATA_LBA; if (scsicmd[0] == VERIFY) { block |= ((u64)scsicmd[2]) << 24; @@ -741,25 +742,53 @@ return 1; } - if (lba48) { - tf->command = ATA_CMD_VERIFY_EXT; + if (lba) { + if (lba48) { + tf->command = ATA_CMD_VERIFY_EXT; + + 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 { + tf->command = ATA_CMD_VERIFY; - tf->hob_nsect = (n_block >> 8) & 0xff; + tf->device |= (block >> 24) & 0xf; + } - 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->nsect = n_block & 0xff; - tf->device |= (block >> 24) & 0xf; - } + tf->lbah = (block >> 16) & 0xff; + tf->lbam = (block >> 8) & 0xff; + tf->lbal = block & 0xff; - tf->nsect = n_block & 0xff; + tf->device |= ATA_LBA; + } else { + /* CHS */ + u32 sect, head, cyl, track; - tf->lbah = (block >> 16) & 0xff; - tf->lbam = (block >> 8) & 0xff; - tf->lbal = block & 0xff; + /* 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->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; } @@ -787,6 +816,8 @@ 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; @@ -845,34 +876,66 @@ /* In ATA, sector count 0 are 256 or 65536 sectors, not 0 sectors. */ return 1; - if (lba48) { - /* The request -may- be too large for LBA48. */ - if ((block >> 48) || (n_block > 65536)) - return 1; + if (lba) { + if (lba48) { + /* The request -may- be too large for LBA48. */ + if ((block >> 48) || (n_block > 65536)) + return 1; + + 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; + + tf->device |= (block >> 24) & 0xf; + } + + qc->nsect = n_block; + tf->nsect = n_block & 0xff; - tf->hob_nsect = (n_block >> 8) & 0xff; + tf->lbah = (block >> 16) & 0xff; + tf->lbam = (block >> 8) & 0xff; + tf->lbal = block & 0xff; - tf->hob_lbah = (block >> 40) & 0xff; - tf->hob_lbam = (block >> 32) & 0xff; - tf->hob_lbal = (block >> 24) & 0xff; + tf->device |= ATA_LBA; } else { - /* LBA28 */ + /* CHS */ + u32 sect, head, cyl, track; - /* The request -may- be too large for LBA28. */ + /* The request -may- be too large for CHS addressing. */ if ((block >> 28) || (n_block > 256)) return 1; - - tf->device |= (block >> 24) & 0xf; + + /* 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; } - - qc->nsect = n_block; - tf->nsect = n_block & 0xff; - - tf->lbah = (block >> 16) & 0xff; - tf->lbam = (block >> 8) & 0xff; - tf->lbal = block & 0xff; - - tf->device |= ATA_LBA; return 0; } @@ -1427,10 +1490,20 @@ 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 */ tmp = n_sectors; /* note: truncates, if lba48 */