* [PATCH libata-dev-2.6 1/3] Add CHS support
@ 2005-02-06 6:02 Albert Lee
2005-02-06 6:26 ` Jeff Garzik
2005-02-18 23:40 ` Jeff Garzik
0 siblings, 2 replies; 28+ messages in thread
From: Albert Lee @ 2005-02-06 6:02 UTC (permalink / raw)
To: Jeff Garzik; +Cc: Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux
[-- Attachment #1: Type: text/plain, Size: 2897 bytes --]
Hi Jeff,
These are the patches for libata CHS support. Tested OK with my old 1994 ST-5850A hardddisk.
Changes:
1. Add the flags, utility function and CHS fields to the <linux/ata.h> and <linux/libata.h> headers.
2. ata_dev_identify() pathed to report and initialize CHS fields in ata_device.
ata_qc_new_init() patched to initialize the ATA_TFLAG_LBA to the ata_taskfile.
3. ata_scsi_verify_xlat(), ata_scsi_rw_xlat() patched to support CHS translation.
ata_scsiop_read_cap() patched to report capacity for CHS-only drives.
Attached please find the patch 1/3 against the libata-dev-2.6 tree for your review. Thanks.
Albert
Signed-off-by: Albert Lee <albertcc@tw.ibm.com>
----------------------------------------------------------------------------------------------
diff -Nru libata-dev-2.6/include/linux/ata.h libata-dev-2.6-mod/include/linux/ata.h
--- libata-dev-2.6/include/linux/ata.h 2005-02-05 10:42:06.000000000 +0800
+++ libata-dev-2.6-mod/include/linux/ata.h 2005-02-05 11:04:33.000000000 +0800
@@ -172,6 +172,7 @@
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 {
@@ -241,6 +242,18 @@
((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;
diff -Nru libata-dev-2.6/include/linux/libata.h libata-dev-2.6-mod/include/linux/libata.h
--- libata-dev-2.6/include/linux/libata.h 2005-02-05 10:42:07.000000000 +0800
+++ libata-dev-2.6-mod/include/linux/libata.h 2005-02-05 11:05:58.000000000 +0800
@@ -95,6 +95,7 @@
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 */
@@ -279,6 +280,11 @@
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 {
[-- Attachment #2: chs1.diff --]
[-- Type: application/octet-stream, Size: 2166 bytes --]
diff -Nru libata-dev-2.6/include/linux/ata.h libata-dev-2.6-mod/include/linux/ata.h
--- libata-dev-2.6/include/linux/ata.h 2005-02-05 10:42:06.000000000 +0800
+++ libata-dev-2.6-mod/include/linux/ata.h 2005-02-05 11:04:33.000000000 +0800
@@ -172,6 +172,7 @@
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 {
@@ -241,6 +242,18 @@
((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;
diff -Nru libata-dev-2.6/include/linux/libata.h libata-dev-2.6-mod/include/linux/libata.h
--- libata-dev-2.6/include/linux/libata.h 2005-02-05 10:42:07.000000000 +0800
+++ libata-dev-2.6-mod/include/linux/libata.h 2005-02-05 11:05:58.000000000 +0800
@@ -95,6 +95,7 @@
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 */
@@ -279,6 +280,11 @@
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 {
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH libata-dev-2.6 1/3] Add CHS support 2005-02-06 6:02 [PATCH libata-dev-2.6 1/3] Add CHS support Albert Lee @ 2005-02-06 6:26 ` Jeff Garzik 2005-02-06 14:41 ` Mark Lord 2005-02-14 11:09 ` Albert Lee 2005-02-18 23:40 ` Jeff Garzik 1 sibling, 2 replies; 28+ messages in thread From: Jeff Garzik @ 2005-02-06 6:26 UTC (permalink / raw) To: Albert Lee Cc: Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux, Mudama, Eric, Mark Lord Thanks for doing this work. Comments: 1) Patches #1 and #2 look OK. 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 Otherwise, patch #3 (content-wise) is OK. 3) In Promise's GPL'd driver for their SATA (w/ PATA) cards, they unconditionally execute the INITIALIZE DEVICE PARAMETERS command. I wonder if we should do the same. 4) I will apply patches #1 and #2 after I receive feedback on my comments in item #3. I have not applied them yet, even though they are acceptable. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6 1/3] Add CHS support 2005-02-06 6:26 ` Jeff Garzik @ 2005-02-06 14:41 ` Mark Lord 2005-02-06 15:00 ` Jeff Garzik 2005-02-14 11:09 ` Albert Lee 1 sibling, 1 reply; 28+ messages in thread From: Mark Lord @ 2005-02-06 14:41 UTC (permalink / raw) To: Jeff Garzik Cc: Albert Lee, Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux, Mudama, Eric Jeff Garzik wrote: > > 3) In Promise's GPL'd driver for their SATA (w/ PATA) cards, they > unconditionally execute the INITIALIZE DEVICE PARAMETERS command. I > wonder if we should do the same. That command was *necessary* for certain drives at one time, which refused all other commands until they received the IDP one. Cheers -- Mark Lord Real-Time Remedies Inc. mlord@pobox.com ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6 1/3] Add CHS support 2005-02-06 14:41 ` Mark Lord @ 2005-02-06 15:00 ` Jeff Garzik 2005-02-06 22:02 ` Mark Lord 0 siblings, 1 reply; 28+ messages in thread From: Jeff Garzik @ 2005-02-06 15:00 UTC (permalink / raw) To: Mark Lord Cc: Albert Lee, Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux, Mudama, Eric Mark Lord wrote: > Jeff Garzik wrote: >> 3) In Promise's GPL'd driver for their SATA (w/ PATA) cards, they >> unconditionally execute the INITIALIZE DEVICE PARAMETERS command. I >> wonder if we should do the same. > > > That command was *necessary* for certain drives at one time, > which refused all other commands until they received the IDP one. Except IDENTIFY DEVICE, presumably? Thanks, Jeff ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6 1/3] Add CHS support 2005-02-06 15:00 ` Jeff Garzik @ 2005-02-06 22:02 ` Mark Lord 0 siblings, 0 replies; 28+ messages in thread From: Mark Lord @ 2005-02-06 22:02 UTC (permalink / raw) To: Jeff Garzik Cc: Albert Lee, Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux, Mudama, Eric The exact sequence expected by certain pre-ATA4 (or earlier?) drives was this: SRST RESET IDENTIFY INITIALIZE DRIVE PARAMETERS anything else.. Some drives were very specific about that exact sequence. Nowadays, I don't bother with it for anything new I do, as it is obsolete, and may even get rejected by modern drives. But for the mainstream Linux ATA support, we should issue it for drives which IDENTIFY themselves as conforming to pre-ATAx, where the safest value for "x" is probably "4". Cheers -- Mark Lord Real-Time Remedies Inc. mlord@pobox.com Jeff Garzik wrote: > Mark Lord wrote: > >> Jeff Garzik wrote: >> >>> 3) In Promise's GPL'd driver for their SATA (w/ PATA) cards, they >>> unconditionally execute the INITIALIZE DEVICE PARAMETERS command. I >>> wonder if we should do the same. >> >> >> >> That command was *necessary* for certain drives at one time, >> which refused all other commands until they received the IDP one. > > > Except IDENTIFY DEVICE, presumably? > > Thanks, > > Jeff > ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6 1/3] Add CHS support 2005-02-06 6:26 ` Jeff Garzik 2005-02-06 14:41 ` Mark Lord @ 2005-02-14 11:09 ` Albert Lee 2005-02-14 11:17 ` Albert Lee 1 sibling, 1 reply; 28+ messages in thread From: Albert Lee @ 2005-02-14 11:09 UTC (permalink / raw) To: Jeff Garzik Cc: Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux, Mudama, Eric, Mark Lord [-- Attachment #1: Type: text/plain, Size: 3547 bytes --] Dear all: > > Comments: > > 1) Patches #1 and #2 look OK. > > 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 > Happy lunar new year. Attached pls find the split patch #3 for your review. Patch 3-1: - rename variables (s/sector/block/) in ata_scsi_verify_xlat() Albert Signed-off-by: Albert Lee <albertcc@tw.ibm.com> ---------------------------------------------------------------------------- --- libata-dev-2.6/drivers/scsi/libata-scsi.c 2005-02-14 16:26:44.000000000 +0800 +++ libata-dev-2.6-mod/drivers/scsi/libata-scsi.c 2005-02-14 16:45:33.000000000 +0800 @@ -691,75 +691,75 @@ struct ata_taskfile *tf = &qc->tf; 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; - 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; + 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_sect & 0xff; + tf->nsect = n_block & 0xff; - tf->lbah = (sect >> 16) & 0xff; - tf->lbam = (sect >> 8) & 0xff; - tf->lbal = sect & 0xff; + tf->lbah = (block >> 16) & 0xff; + tf->lbam = (block >> 8) & 0xff; + tf->lbal = block & 0xff; return 0; } [-- Attachment #2: chs3-1.diff --] [-- Type: application/octet-stream, Size: 3148 bytes --] --- libata-dev-2.6/drivers/scsi/libata-scsi.c 2005-02-14 16:26:44.000000000 +0800 +++ libata-dev-2.6-mod/drivers/scsi/libata-scsi.c 2005-02-14 16:45:33.000000000 +0800 @@ -691,75 +691,75 @@ struct ata_taskfile *tf = &qc->tf; 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; - 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; + 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_sect & 0xff; + tf->nsect = n_block & 0xff; - tf->lbah = (sect >> 16) & 0xff; - tf->lbam = (sect >> 8) & 0xff; - tf->lbal = sect & 0xff; + tf->lbah = (block >> 16) & 0xff; + tf->lbam = (block >> 8) & 0xff; + tf->lbal = block & 0xff; return 0; } ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6 1/3] Add CHS support 2005-02-14 11:09 ` Albert Lee @ 2005-02-14 11:17 ` Albert Lee 2005-02-14 11:23 ` Albert Lee 0 siblings, 1 reply; 28+ messages in thread From: Albert Lee @ 2005-02-14 11:17 UTC (permalink / raw) To: Jeff Garzik Cc: Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux, Mudama, Eric, Mark Lord [-- Attachment #1: Type: text/plain, Size: 4667 bytes --] > 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-2: - reorganize read/write translation in ata_scsi_rw_xlat() Albert Signed-off-by: Albert Lee <albertcc@tw.ibm.com> ------------------------------------------------------------------ --- libata-dev-2.6/drivers/scsi/libata-scsi.c 2005-02-14 16:54:47.000000000 +0800 +++ libata-dev-2.6-mod/drivers/scsi/libata-scsi.c 2005-02-14 17:05:12.000000000 +0800 @@ -788,10 +788,11 @@ { struct ata_taskfile *tf = &qc->tf; 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) { @@ -801,80 +802,79 @@ 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]; - - 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]; + block |= ((u64)scsicmd[2]) << 24; + block |= ((u64)scsicmd[3]) << 16; + block |= ((u64)scsicmd[4]) << 8; + block |= ((u64)scsicmd[5]); - 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"); - return 0; - } - - if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) { - qc->nsect = tf->nsect = scsicmd[4]; - 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]); + 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]); - 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; + VPRINTK("sixteen-byte command\n"); + } else { + DPRINTK("no-byte command\n"); + return 1; + } - if (lba48) { - tf->hob_nsect = scsicmd[12]; - tf->hob_lbal = scsicmd[6]; - tf->hob_lbam = scsicmd[5]; - tf->hob_lbah = scsicmd[4]; + /* Check and compose ATA command */ + if (!n_block) + /* In ATA, sector count 0 are 256 or 65536 sectors, not 0 sectors. */ + return 1; - 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)) - return 1; + if (lba48) { + /* 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; - qc->nsect = scsicmd[13]; - } + tf->hob_lbah = (block >> 40) & 0xff; + tf->hob_lbam = (block >> 32) & 0xff; + tf->hob_lbal = (block >> 24) & 0xff; + } else { + /* LBA28 */ - tf->nsect = scsicmd[13]; - tf->lbal = scsicmd[9]; - tf->lbam = scsicmd[8]; - tf->lbah = scsicmd[7]; + /* The request -may- be too large for LBA28. */ + if ((block >> 28) || (n_block > 256)) + return 1; - VPRINTK("sixteen-byte command\n"); - return 0; + tf->device |= (block >> 24) & 0xf; } + + qc->nsect = n_block; + tf->nsect = n_block & 0xff; + + tf->lbah = (block >> 16) & 0xff; + tf->lbam = (block >> 8) & 0xff; + tf->lbal = block & 0xff; - DPRINTK("no-byte command\n"); - return 1; + tf->device |= ATA_LBA; + + return 0; } static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) [-- Attachment #2: chs3-2.diff --] [-- Type: application/octet-stream, Size: 4460 bytes --] --- libata-dev-2.6/drivers/scsi/libata-scsi.c 2005-02-14 16:54:47.000000000 +0800 +++ libata-dev-2.6-mod/drivers/scsi/libata-scsi.c 2005-02-14 17:05:12.000000000 +0800 @@ -788,10 +788,11 @@ { struct ata_taskfile *tf = &qc->tf; 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) { @@ -801,80 +802,79 @@ 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]; - - 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]; + block |= ((u64)scsicmd[2]) << 24; + block |= ((u64)scsicmd[3]) << 16; + block |= ((u64)scsicmd[4]) << 8; + block |= ((u64)scsicmd[5]); - 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"); - return 0; - } - - if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) { - qc->nsect = tf->nsect = scsicmd[4]; - 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]); + 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]); - 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; + VPRINTK("sixteen-byte command\n"); + } else { + DPRINTK("no-byte command\n"); + return 1; + } - if (lba48) { - tf->hob_nsect = scsicmd[12]; - tf->hob_lbal = scsicmd[6]; - tf->hob_lbam = scsicmd[5]; - tf->hob_lbah = scsicmd[4]; + /* Check and compose ATA command */ + if (!n_block) + /* In ATA, sector count 0 are 256 or 65536 sectors, not 0 sectors. */ + return 1; - 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)) - return 1; + if (lba48) { + /* 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; - qc->nsect = scsicmd[13]; - } + tf->hob_lbah = (block >> 40) & 0xff; + tf->hob_lbam = (block >> 32) & 0xff; + tf->hob_lbal = (block >> 24) & 0xff; + } else { + /* LBA28 */ - tf->nsect = scsicmd[13]; - tf->lbal = scsicmd[9]; - tf->lbam = scsicmd[8]; - tf->lbah = scsicmd[7]; + /* The request -may- be too large for LBA28. */ + if ((block >> 28) || (n_block > 256)) + return 1; - VPRINTK("sixteen-byte command\n"); - return 0; + tf->device |= (block >> 24) & 0xf; } + + qc->nsect = n_block; + tf->nsect = n_block & 0xff; + + tf->lbah = (block >> 16) & 0xff; + tf->lbam = (block >> 8) & 0xff; + tf->lbal = block & 0xff; - DPRINTK("no-byte command\n"); - return 1; + tf->device |= ATA_LBA; + + return 0; } static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6 1/3] Add CHS support 2005-02-14 11:17 ` Albert Lee @ 2005-02-14 11:23 ` Albert Lee 0 siblings, 0 replies; 28+ messages in thread From: Albert Lee @ 2005-02-14 11:23 UTC (permalink / raw) To: Jeff Garzik Cc: Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux, Mudama, Eric, Mark Lord [-- Attachment #1: Type: text/plain, Size: 5954 bytes --] > 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 <albertcc@tw.ibm.com> ------------------------------------------------------------------ --- 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 */ [-- Attachment #2: chs3-3.diff --] [-- Type: application/octet-stream, Size: 5769 bytes --] --- 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 */ ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6 1/3] Add CHS support 2005-02-06 6:02 [PATCH libata-dev-2.6 1/3] Add CHS support Albert Lee 2005-02-06 6:26 ` Jeff Garzik @ 2005-02-18 23:40 ` Jeff Garzik 2005-02-22 3:35 ` Albert Lee 2005-02-23 11:25 ` [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices Albert Lee 1 sibling, 2 replies; 28+ messages in thread From: Jeff Garzik @ 2005-02-18 23:40 UTC (permalink / raw) To: Albert Lee; +Cc: Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux, Mark Lord Applied patches 1 and 2 of the first CHS series, and patches 3-1 through 3-3 of the second CHS series, to libata-dev queue. As a follow-up, I believe libata-core should be modified to issue the INITIALIZE DEVICE PARAMETERS command for all CHS devices. Thanks, Jeff ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6 1/3] Add CHS support 2005-02-18 23:40 ` Jeff Garzik @ 2005-02-22 3:35 ` Albert Lee 2005-02-23 11:25 ` [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices Albert Lee 1 sibling, 0 replies; 28+ messages in thread From: Albert Lee @ 2005-02-22 3:35 UTC (permalink / raw) To: Jeff Garzik; +Cc: Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux, Mark Lord Jeff, > Applied patches 1 and 2 of the first CHS series, > and patches 3-1 through 3-3 of the second CHS series, to libata-dev queue. > Thanks. > As a follow-up, I believe libata-core should be modified to issue the > INITIALIZE DEVICE PARAMETERS command for all CHS devices. > I will work on this, according to the discussion on the issue. Albert ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices 2005-02-18 23:40 ` Jeff Garzik 2005-02-22 3:35 ` Albert Lee @ 2005-02-23 11:25 ` Albert Lee 2005-02-23 14:48 ` Mark Lord 2005-02-23 16:50 ` Bartlomiej Zolnierkiewicz 1 sibling, 2 replies; 28+ messages in thread From: Albert Lee @ 2005-02-23 11:25 UTC (permalink / raw) To: Jeff Garzik; +Cc: Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux, Mark Lord > Applied patches 1 and 2 of the first CHS series, > and patches 3-1 through 3-3 of the second CHS series, to libata-dev queue. > > As a follow-up, I believe libata-core should be modified to issue the > INITIALIZE DEVICE PARAMETERS command for all CHS devices. > Jeff, This is the patch to issue INITIALIZE DEVICE PARAMETERS for CHS only devices. Changes: 1. Add ATA_CMD_INIT_DEV_PARAMS to the <linux/ata.h>. 2. Add ata_dev_init_params() and call it for ATA0-ATA3 CHS-only devices. 3. Fix uninitialized tf->command in ata_scsi_verify_xlat() and comment. Attached please find the patch against the libata-dev-2.6 tree for your review. Albert Signed-off-by: Albert Lee <albertcc@tw.ibm.com> ============================================================================================== --- libata-dev-2.6/include/linux/ata.h 2005-02-21 17:23:19.000000000 +0800 +++ libata-dev-2.6-mod/include/linux/ata.h 2005-02-23 17:28:42.000000000 +0800 @@ -125,6 +125,7 @@ ATA_CMD_PACKET = 0xA0, ATA_CMD_VERIFY = 0x40, ATA_CMD_VERIFY_EXT = 0x42, + ATA_CMD_INIT_DEV_PARAMS = 0x91, /* SETFEATURES stuff */ SETFEATURES_XFER = 0x03, --- libata-dev-2.6/drivers/scsi/libata-core.c 2005-02-21 17:23:03.000000000 +0800 +++ libata-dev-2.6-mod/drivers/scsi/libata-core.c 2005-02-23 19:08:57.000000000 +0800 @@ -52,6 +52,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); @@ -1085,6 +1086,10 @@ dev->sectors = dev->id[6]; dev->n_sectors = dev->cylinders * dev->heads * dev->sectors; + if (major_version < 4) + /* For newer devices, INIT DEVICE PARAMS is obsolete */ + ata_dev_init_params(ap, dev); + if (ata_id_current_chs_valid(dev->id)) { /* Current CHS translation is valid. */ dev->cylinders = dev->id[54]; @@ -1893,6 +1898,48 @@ } /** + * 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; + + /* 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 = dev->sectors; + qc->tf.device |= (dev->heads - 1) & 0x0f; + + 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 - * @qc: * --- libata-dev-2.6/drivers/scsi/libata-scsi.c 2005-02-21 17:23:03.000000000 +0800 +++ libata-dev-2.6-mod/drivers/scsi/libata-scsi.c 2005-02-22 18:32:19.000000000 +0800 @@ -785,6 +785,7 @@ 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; @@ -875,7 +876,7 @@ /* Check and compose ATA command */ if (!n_block) - /* In ATA, sector count 0 are 256 or 65536 sectors, not 0 sectors. */ + /* In ATA, sector count 0 means 256 or 65536 sectors, not 0 sectors. */ return 1; if (lba) { ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices 2005-02-23 11:25 ` [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices Albert Lee @ 2005-02-23 14:48 ` Mark Lord 2005-02-24 2:36 ` Albert Lee 2005-02-23 16:50 ` Bartlomiej Zolnierkiewicz 1 sibling, 1 reply; 28+ messages in thread From: Mark Lord @ 2005-02-23 14:48 UTC (permalink / raw) To: Albert Lee; +Cc: Jeff Garzik, Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux >This is the patch to issue INITIALIZE DEVICE PARAMETERS >for CHS only devices. That comment is not accurate. What the patch really does is issue the IDP command for devices predating ATA-4, regardless of whether they are CHS-only or not. Correct behaviour, mind you. Just the comment appeared misleading. Oh, and what is the "major_version" variable based on? I don't see it in 2.6.11-rc4, so it must be in the libata bk stuff. For this usage to work, that variable has to be set from the drive IDENTIFY data, but with a precautionary check for drives (pre-ATA4) which may not set the version at all. I'm guessing this is already taken care of elsewhere in libata, right? Cheers -- Mark Lord Real-Time Remedies Inc. mlord@pobox.com ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices 2005-02-23 14:48 ` Mark Lord @ 2005-02-24 2:36 ` Albert Lee 2005-02-24 2:53 ` Jeff Garzik 2005-02-24 3:10 ` Mark Lord 0 siblings, 2 replies; 28+ messages in thread From: Albert Lee @ 2005-02-24 2:36 UTC (permalink / raw) To: Mark Lord; +Cc: Jeff Garzik, Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux Mark Lord wrote: > >This is the patch to issue INITIALIZE DEVICE PARAMETERS > >for CHS only devices. > > That comment is not accurate. What the patch really does > is issue the IDP command for devices predating ATA-4, > regardless of whether they are CHS-only or not. The Promise GPL'ed code does that, no matter whether the device supports LBA or not. Nor checking the ATA major version, they just issue IDP to the device. However, it seems IDP is closely related to CHS. So in my patch, I just issue it for the CHS-only (i.e. no LBA support) devices. If the device supports LBA, then IDP is not issued in my patch. Is this OK? > > Oh, and what is the "major_version" variable based on? > I don't see it in 2.6.11-rc4, so it must be in the libata bk stuff. The "major_version" is the "i" variable in the ata_dev_identify(). Renamed in the previous CHS patch for clarity. > > For this usage to work, that variable has to be set from the > drive IDENTIFY data, but with a precautionary check for drives > (pre-ATA4) which may not set the version at all. I'm guessing > this is already taken care of elsewhere in libata, right? > Yes, it is already taken care in libata. It is from the IDENTIFY data. Tested with my 1995 Seagate drive, it reports ATA-0 for the major version on libata. No problem reading/writing it. However, I have to remove the pre ATA-3 check code before testing it. Best regards, Albert ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices 2005-02-24 2:36 ` Albert Lee @ 2005-02-24 2:53 ` Jeff Garzik 2005-02-24 5:29 ` Albert Lee 2005-02-24 3:10 ` Mark Lord 1 sibling, 1 reply; 28+ messages in thread From: Jeff Garzik @ 2005-02-24 2:53 UTC (permalink / raw) To: Albert Lee; +Cc: Mark Lord, Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux Albert Lee wrote: > No problem reading/writing it. However, I have to remove the pre ATA-3 > check code before testing it. Now that CHS support is present, I am OK with removing the "pre ATA-3" version check. Jeff ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices 2005-02-24 2:53 ` Jeff Garzik @ 2005-02-24 5:29 ` Albert Lee 2005-02-24 5:35 ` Jeff Garzik 0 siblings, 1 reply; 28+ messages in thread From: Albert Lee @ 2005-02-24 5:29 UTC (permalink / raw) To: Jeff Garzik; +Cc: Mark Lord, Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux Jeff Garzik wrote: >> No problem reading/writing it. However, I have to remove the pre ATA-3 >> check code before testing it. > > Now that CHS support is present, I am OK with removing the "pre ATA-3" > version check. > I'll remove this check in the IDP patch and resubmit the patch. Albert ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices 2005-02-24 5:29 ` Albert Lee @ 2005-02-24 5:35 ` Jeff Garzik 2005-02-24 6:41 ` Albert Lee 0 siblings, 1 reply; 28+ messages in thread From: Jeff Garzik @ 2005-02-24 5:35 UTC (permalink / raw) To: Albert Lee; +Cc: Mark Lord, Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux Albert Lee wrote: > Jeff Garzik wrote: >> Now that CHS support is present, I am OK with removing the "pre ATA-3" >> version check. > I'll remove this check in the IDP patch and resubmit the patch. Thanks. Please use the logic Mark described: > if (ATA < 4 || !lba_capable) > issue IDP command > else > no need for IDP command Jeff ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices 2005-02-24 5:35 ` Jeff Garzik @ 2005-02-24 6:41 ` Albert Lee 2005-02-24 6:48 ` Jeff Garzik 0 siblings, 1 reply; 28+ messages in thread From: Albert Lee @ 2005-02-24 6:41 UTC (permalink / raw) To: Jeff Garzik; +Cc: Mark Lord, Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux Jeff Garzik wrote: > Thanks. Please use the logic Mark described: > >> if (ATA < 4 || !lba_capable) >> issue IDP command >> else >> no need for IDP command > Thanks for the detailed instruction. Attached please find the revised patch for your review. Albert Signed-off-by: Albert Lee <albertcc@tw.ibm.com> ============================================================================================= --- libata-dev-2.6/include/linux/ata.h 2005-02-21 17:23:19.000000000 +0800 +++ libata-dev-2.6-mod/include/linux/ata.h 2005-02-23 17:28:42.000000000 +0800 @@ -125,6 +125,7 @@ ATA_CMD_PACKET = 0xA0, ATA_CMD_VERIFY = 0x40, ATA_CMD_VERIFY_EXT = 0x42, + ATA_CMD_INIT_DEV_PARAMS = 0x91, /* SETFEATURES stuff */ SETFEATURES_XFER = 0x03, --- libata-dev-2.6/drivers/scsi/libata-core.c 2005-02-21 17:23:03.000000000 +0800 +++ libata-dev-2.6-mod/drivers/scsi/libata-core.c 2005-02-24 14:35:55.000000000 +0800 @@ -52,6 +52,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); @@ -1053,11 +1054,16 @@ if (tmp & (1 << major_version)) break; - /* we require at least ATA-3 */ - if (major_version < 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; @@ -1893,6 +1899,54 @@ } /** + * 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 = number 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 - * @qc: * --- libata-dev-2.6/drivers/scsi/libata-scsi.c 2005-02-21 17:23:03.000000000 +0800 +++ libata-dev-2.6-mod/drivers/scsi/libata-scsi.c 2005-02-22 18:32:19.000000000 +0800 @@ -785,6 +785,7 @@ 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; @@ -875,7 +876,7 @@ /* Check and compose ATA command */ if (!n_block) - /* In ATA, sector count 0 are 256 or 65536 sectors, not 0 sectors. */ + /* In ATA, sector count 0 means 256 or 65536 sectors, not 0 sectors. */ return 1; if (lba) { ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices 2005-02-24 6:41 ` Albert Lee @ 2005-02-24 6:48 ` Jeff Garzik 2005-02-24 7:01 ` Albert Lee 0 siblings, 1 reply; 28+ messages in thread From: Jeff Garzik @ 2005-02-24 6:48 UTC (permalink / raw) To: Albert Lee; +Cc: Mark Lord, Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux Albert Lee wrote: > Thanks for the detailed instruction. > Attached please find the revised patch for your review. Thanks for the updated patch. Patch looks OK except: > --- libata-dev-2.6/drivers/scsi/libata-scsi.c 2005-02-21 > 17:23:03.000000000 +0800 > +++ libata-dev-2.6-mod/drivers/scsi/libata-scsi.c 2005-02-22 > 18:32:19.000000000 +0800 > @@ -785,6 +785,7 @@ > 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; > @@ -875,7 +876,7 @@ > > /* Check and compose ATA command */ > if (!n_block) > - /* In ATA, sector count 0 are 256 or 65536 sectors, not 0 > sectors. */ > + /* In ATA, sector count 0 means 256 or 65536 sectors, not 0 > sectors. */ Please submit these libata-scsi changes in a separate patch. Jeff ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices 2005-02-24 6:48 ` Jeff Garzik @ 2005-02-24 7:01 ` Albert Lee 2005-02-24 7:48 ` Jeff Garzik 0 siblings, 1 reply; 28+ messages in thread From: Albert Lee @ 2005-02-24 7:01 UTC (permalink / raw) To: Jeff Garzik; +Cc: Mark Lord, Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux Jeff Garzik wrote: > > > Please submit these libata-scsi changes in a separate patch. > > The IDP patch with split libata-scsi fix. Attached please find the revised patch for your review. Albert Signed-off-by: Albert Lee <albertcc@tw.ibm.com> ============================================================================================= --- libata-dev-2.6/include/linux/ata.h 2005-02-21 17:23:19.000000000 +0800 +++ libata-dev-2.6-mod/include/linux/ata.h 2005-02-23 17:28:42.000000000 +0800 @@ -125,6 +125,7 @@ ATA_CMD_PACKET = 0xA0, ATA_CMD_VERIFY = 0x40, ATA_CMD_VERIFY_EXT = 0x42, + ATA_CMD_INIT_DEV_PARAMS = 0x91, /* SETFEATURES stuff */ SETFEATURES_XFER = 0x03, --- libata-dev-2.6/drivers/scsi/libata-core.c 2005-02-21 17:23:03.000000000 +0800 +++ libata-dev-2.6-mod/drivers/scsi/libata-core.c 2005-02-24 14:35:55.000000000 +0800 @@ -52,6 +52,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); @@ -1053,11 +1054,16 @@ if (tmp & (1 << major_version)) break; - /* we require at least ATA-3 */ - if (major_version < 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; @@ -1893,6 +1899,54 @@ } /** + * 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 = number 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 - * @qc: * ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices 2005-02-24 7:01 ` Albert Lee @ 2005-02-24 7:48 ` Jeff Garzik 2005-02-25 5:01 ` Albert Lee 0 siblings, 1 reply; 28+ messages in thread From: Jeff Garzik @ 2005-02-24 7:48 UTC (permalink / raw) To: Albert Lee; +Cc: Mark Lord, Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux [-- Attachment #1: Type: text/plain, Size: 1063 bytes --] This patch similarly fails to apply: include/linux/ata.h 1.23: 281 lines include/linux/ata.h 1.23 -> 1.24: 281 lines 1 out of 1 hunk FAILED -- saving rejects to file include/linux/ata.h.rej drivers/scsi/libata-core.c 1.121: 4064 lines drivers/scsi/libata-core.c 1.121 -> 1.122: 4064 lines 2 out of 3 hunks FAILED -- saving rejects to file drivers/scsi/libata-core.c.rej Here at home, I have many trees, all diff'd against 2.6.11-rc4: adma/ atapi-enable/ iomap/ promise-sata-pata/ via-6421/ adma-mwi/ bridge-detect/ passthru/ remove-one-fix/ ahci-msi/ chs-support/ pdc2027x/ sata-sil-irq/ ALL/ ioctl-get-identity/ pdc20619/ tf-cleanup/ When I receive a C/H/S patch from you, I apply it to the "chs-support" tree, which is 2.6.11-rc4 + your C/H/S patches When I receive a pata_pdc2027x patch from you, I apply it to the "pdc2027x" tree, which is 2.6.11-rc4 + your pata_pdc2027x patches I have attached the cumulative patch for "chs-support" tree, if this helps you re-diff your changes. Regards, Jeff [-- Attachment #2: patch --] [-- Type: text/plain, Size: 15386 bytes --] diff -Nru a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c --- a/drivers/scsi/libata-core.c 2005-02-24 02:47:53 -05:00 +++ b/drivers/scsi/libata-core.c 2005-02-24 02:47:53 -05:00 @@ -1008,7 +1008,7 @@ 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; @@ -1106,9 +1106,9 @@ * 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; } @@ -1128,32 +1128,64 @@ 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) { + if (major_version < 3) { printk(KERN_DEBUG "ata%u: no ATA-3\n", ap->id); goto err_out_nosup; } - 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); + 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); + } 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 */ @@ -2736,8 +2768,12 @@ 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; diff -Nru a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c --- a/drivers/scsi/libata-scsi.c 2005-02-24 02:47:53 -05:00 +++ b/drivers/scsi/libata-scsi.c 2005-02-24 02:47:53 -05:00 @@ -435,77 +435,106 @@ 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_sect & 0xff; + tf->nsect = n_block & 0xff; - tf->lbah = (sect >> 16) & 0xff; - tf->lbam = (sect >> 8) & 0xff; - tf->lbal = sect & 0xff; + tf->lbah = (block >> 16) & 0xff; + tf->lbam = (block >> 8) & 0xff; + tf->lbal = block & 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->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; } @@ -533,11 +562,14 @@ 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) { @@ -547,80 +579,111 @@ 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]; - - 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]; + block |= ((u64)scsicmd[2]) << 24; + block |= ((u64)scsicmd[3]) << 16; + block |= ((u64)scsicmd[4]) << 8; + block |= ((u64)scsicmd[5]); - 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"); - return 0; - } - - if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) { - qc->nsect = tf->nsect = scsicmd[4]; - 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]); + 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 are 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; - qc->nsect = scsicmd[13]; - } + tf->hob_lbah = (block >> 40) & 0xff; + tf->hob_lbam = (block >> 32) & 0xff; + tf->hob_lbal = (block >> 24) & 0xff; + } else { + /* LBA28 */ - tf->nsect = scsicmd[13]; - tf->lbal = scsicmd[9]; - tf->lbam = scsicmd[8]; - tf->lbah = scsicmd[7]; + /* The request -may- be too large for LBA28. */ + if ((block >> 28) || (n_block > 256)) + return 1; - VPRINTK("sixteen-byte command\n"); - return 0; + tf->device |= (block >> 24) & 0xf; + } + + 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; + } else { + /* CHS */ + u32 sect, head, cyl, track; + + /* The request -may- be too large for CHS addressing. */ + if ((block >> 28) || (n_block > 256)) + return 1; + + /* 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) @@ -1162,10 +1225,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 */ diff -Nru a/include/linux/ata.h b/include/linux/ata.h --- a/include/linux/ata.h 2005-02-24 02:47:53 -05:00 +++ b/include/linux/ata.h 2005-02-24 02:47:53 -05:00 @@ -174,6 +174,7 @@ 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 { @@ -241,6 +242,18 @@ ((u64) (id)[(n) + 2] << 32) | \ ((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) { diff -Nru a/include/linux/libata.h b/include/linux/libata.h --- a/include/linux/libata.h 2005-02-24 02:47:53 -05:00 +++ b/include/linux/libata.h 2005-02-24 02:47:53 -05:00 @@ -95,6 +95,7 @@ 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 */ @@ -278,6 +279,11 @@ 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 { ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices 2005-02-24 7:48 ` Jeff Garzik @ 2005-02-25 5:01 ` Albert Lee 2005-02-25 5:22 ` Albert Lee 2005-02-25 5:40 ` Jeff Garzik 0 siblings, 2 replies; 28+ messages in thread From: Albert Lee @ 2005-02-25 5:01 UTC (permalink / raw) To: Jeff Garzik; +Cc: Mark Lord, Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux > > This patch similarly fails to apply: > Jeff, Rediff'ed against 2.6.11-rc5 + C/H/S patches. Attached please find the revised patch for your review. Albert Signed-off-by: Albert Lee <albertcc@tw.ibm.com> ============================================================================================ --- linux-2.6.11-rc5-chs/include/linux/ata.h 2005-02-25 11:49:46.000000000 +0800 +++ linux-2.6.11-rc5-mod/include/linux/ata.h 2005-02-25 12:30:57.000000000 +0800 @@ -125,6 +125,7 @@ ATA_CMD_PACKET = 0xA0, ATA_CMD_VERIFY = 0x40, ATA_CMD_VERIFY_EXT = 0x42, + ATA_CMD_INIT_DEV_PARAMS = 0x91, /* SETFEATURES stuff */ SETFEATURES_XFER = 0x03, --- linux-2.6.11-rc5-chs/drivers/scsi/libata-core.c 2005-02-25 11:48:23.000000000 +0800 +++ linux-2.6.11-rc5-mod/drivers/scsi/libata-core.c 2005-02-25 12:35:33.000000000 +0800 @@ -52,6 +52,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); @@ -1134,11 +1135,16 @@ if (tmp & (1 << major_version)) break; - /* we require at least ATA-3 */ - if (major_version < 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; @@ -1979,6 +1985,54 @@ } /** + * 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 = number 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 - * @qc: * ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices 2005-02-25 5:01 ` Albert Lee @ 2005-02-25 5:22 ` Albert Lee 2005-02-25 5:40 ` Jeff Garzik 1 sibling, 0 replies; 28+ messages in thread From: Albert Lee @ 2005-02-25 5:22 UTC (permalink / raw) To: Jeff Garzik; +Cc: Mark Lord, Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux Albert Lee wrote: > > Rediff'ed against 2.6.11-rc5 + C/H/S patches. > Attached please find the revised patch for your review. > I forgot to mention. The correct title, as indicated by Mark, should be: "Issue INITIALIZE DEVICE PARAMETERS for pre-ATA4 or CHS only devices" Albert ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices 2005-02-25 5:01 ` Albert Lee 2005-02-25 5:22 ` Albert Lee @ 2005-02-25 5:40 ` Jeff Garzik 1 sibling, 0 replies; 28+ messages in thread From: Jeff Garzik @ 2005-02-25 5:40 UTC (permalink / raw) To: Albert Lee; +Cc: Mark Lord, Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux This patch also looked perfect, and also did not apply. I don't understand this, either. I applied this patch manually also. Thanks much! Jeff ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices 2005-02-24 2:36 ` Albert Lee 2005-02-24 2:53 ` Jeff Garzik @ 2005-02-24 3:10 ` Mark Lord 2005-02-24 3:15 ` Jeff Garzik 1 sibling, 1 reply; 28+ messages in thread From: Mark Lord @ 2005-02-24 3:10 UTC (permalink / raw) To: Albert Lee; +Cc: Jeff Garzik, Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux Albert Lee wrote: > > If the device supports LBA, then IDP is not issued in my patch. Is > this OK? It has been about a decade, but my memory vaguely suggests that I tried that once before, and some LBA-capable drives still required the IDP before they would function normally. I think anything ATA-4 or later was fine, though. Cheers -- Mark Lord Real-Time Remedies Inc. mlord@pobox.com ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices 2005-02-24 3:10 ` Mark Lord @ 2005-02-24 3:15 ` Jeff Garzik 2005-02-24 3:35 ` Mark Lord 0 siblings, 1 reply; 28+ messages in thread From: Jeff Garzik @ 2005-02-24 3:15 UTC (permalink / raw) To: Mark Lord; +Cc: Albert Lee, Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux Mark Lord wrote: > Albert Lee wrote: > >> >> If the device supports LBA, then IDP is not issued in my patch. Is >> this OK? > > > It has been about a decade, but my memory vaguely suggests > that I tried that once before, and some LBA-capable drives > still required the IDP before they would function normally. > > I think anything ATA-4 or later was fine, though. So a safe rule would be if (ATA < 4) issue init-dev-params if (lba) ...current code... else /* CHS */ ...current code... ? Jeff ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices 2005-02-24 3:15 ` Jeff Garzik @ 2005-02-24 3:35 ` Mark Lord 0 siblings, 0 replies; 28+ messages in thread From: Mark Lord @ 2005-02-24 3:35 UTC (permalink / raw) To: Jeff Garzik Cc: Mark Lord, Albert Lee, Bartlomiej Zolnierkiewicz, Doug Maxey, IDE Linux >> It has been about a decade, but my memory vaguely suggests >> that I tried that once before, and some LBA-capable drives >> still required the IDP before they would function normally. >> >> I think anything ATA-4 or later was fine, though. So.. if (ATA < 4 || !lba_capable) issue IDP command else no need for IDP command Cheers ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices 2005-02-23 11:25 ` [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices Albert Lee 2005-02-23 14:48 ` Mark Lord @ 2005-02-23 16:50 ` Bartlomiej Zolnierkiewicz 2005-02-24 3:05 ` Albert Lee 1 sibling, 1 reply; 28+ messages in thread From: Bartlomiej Zolnierkiewicz @ 2005-02-23 16:50 UTC (permalink / raw) To: Albert Lee; +Cc: Jeff Garzik, Doug Maxey, IDE Linux, Mark Lord Hi, [ generic comment about PATA support in libata, yes wrong thread 8) ] I think that at one point libata and IDE drivers should be merged. Yes, this is doable and I plan to prove it soon (this shouldn't be so hard nowadays :-). I really don't want to have two PATA drivers in the tree with subtle differences (i.e. CHS handling) when one would work in some cases (i.e. 4 Promise controllers) and the second one in other cases (i.e. ATAPI support). I'm sure you get the point. Cheers, Bartlomiej ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices 2005-02-23 16:50 ` Bartlomiej Zolnierkiewicz @ 2005-02-24 3:05 ` Albert Lee 0 siblings, 0 replies; 28+ messages in thread From: Albert Lee @ 2005-02-24 3:05 UTC (permalink / raw) To: Bartlomiej Zolnierkiewicz; +Cc: Jeff Garzik, Doug Maxey, IDE Linux, Mark Lord Hi Bart, > > [ generic comment about PATA support in libata, yes wrong thread 8) ] > > I think that at one point libata and IDE drivers should be merged. > Yes, this is doable and I plan to prove it soon (this shouldn't be so > hard nowadays :-). Do you mean the IDE subsystem and libata sharing the same lowlevel drivers? > I really don't want to have two PATA drivers in > the tree with subtle differences (i.e. CHS handling) when one would > work in some cases (i.e. 4 Promise controllers) and the second one > in other cases (i.e. ATAPI support). I'm sure you get the point. > Yes, it is a problem. When I was asked to look at pdc2027x host adapter hotplug issue, I saw libata already have the HBA hotplug feature. So, that's why the pdc202xx_new driver was ported to libata as pata_pdc202xx driver. However, currently libata needs enhancements like PATA, ATAPI, etc. And the IDE subsystem needs some enhancements like HBA hotplug, etc. It will be great if some kind of integration can be done. Before the dream come true, could I work on the following items on pdc202xx_new driver? - Add PLL init code (This can fix the more than 2 adapters not supported limitation) - Fix the hardware auto-set timing registers problem - Fix the pdc2027x ATAPI DMA problem with the workaround (Currently pdc202xx_new driver alway use PIO mode for ATAPI) The pdc202xx_new is the current driver used in production environment. Fixing the above problems is really needed. Best regards, Albert ^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2005-02-25 5:40 UTC | newest] Thread overview: 28+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2005-02-06 6:02 [PATCH libata-dev-2.6 1/3] Add CHS support Albert Lee 2005-02-06 6:26 ` Jeff Garzik 2005-02-06 14:41 ` Mark Lord 2005-02-06 15:00 ` Jeff Garzik 2005-02-06 22:02 ` Mark Lord 2005-02-14 11:09 ` Albert Lee 2005-02-14 11:17 ` Albert Lee 2005-02-14 11:23 ` Albert Lee 2005-02-18 23:40 ` Jeff Garzik 2005-02-22 3:35 ` Albert Lee 2005-02-23 11:25 ` [PATCH libata-dev-2.6] Issue INITIALIZE DEVICE PARAMETERS for CHS only devices Albert Lee 2005-02-23 14:48 ` Mark Lord 2005-02-24 2:36 ` Albert Lee 2005-02-24 2:53 ` Jeff Garzik 2005-02-24 5:29 ` Albert Lee 2005-02-24 5:35 ` Jeff Garzik 2005-02-24 6:41 ` Albert Lee 2005-02-24 6:48 ` Jeff Garzik 2005-02-24 7:01 ` Albert Lee 2005-02-24 7:48 ` Jeff Garzik 2005-02-25 5:01 ` Albert Lee 2005-02-25 5:22 ` Albert Lee 2005-02-25 5:40 ` Jeff Garzik 2005-02-24 3:10 ` Mark Lord 2005-02-24 3:15 ` Jeff Garzik 2005-02-24 3:35 ` Mark Lord 2005-02-23 16:50 ` Bartlomiej Zolnierkiewicz 2005-02-24 3:05 ` Albert Lee
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).