> 2) Patch #3 needs to be split up into three patches: > a) rename variables (s/sector/block/), > b) reorganize read/write translation > c) add CHS support >
Patch 3-3:
- add CHS support to ata_scsi_verify_xlat(), ata_scsi_rw_xlat() and
ata_scsiop_read_cap().
Albert
Signed-off-by: Albert Lee <[EMAIL PROTECTED]>
------------------------------------------------------------------
--- 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 */
chs3-3.diff
Description: Binary data
