Subject: [patch ide-dev 3/9] merge LBA28 and LBA48 Host Protected Area support code


* merge idedisk_read_native_max_address()
and idedisk_read_native_max_address_ext()
* merge idedisk_set_max_address()
and idedisk_set_max_address_ext()

diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
--- a/drivers/ide/ide-disk.c 2005-02-19 17:22:44 +01:00
+++ b/drivers/ide/ide-disk.c 2005-02-19 17:22:44 +01:00
@@ -325,32 +325,7 @@
* Queries for true maximum capacity of the drive.
* Returns maximum LBA address (> 0) of the drive, 0 if failed.
*/
-static unsigned long idedisk_read_native_max_address(ide_drive_t *drive)
-{
- ide_task_t args;
- struct ata_taskfile *tf = &args.tf;
- unsigned long addr = 0;
-
- /* Create IDE/ATA command request structure */
- memset(&args, 0, sizeof(ide_task_t));
-
- tf->device = 0x40;
- tf->command = WIN_READ_NATIVE_MAX;
-
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.handler = &task_no_data_intr;
- /* submit command request */
- ide_raw_taskfile(drive, &args, NULL);
-
- /* if OK, compute maximum address value */
- if ((tf->command & 1) == 0) {
- addr = (u32)ide_tf_get_address(tf);
- addr++; /* since the return value is (maxlba - 1), we add 1 */
- }
- return addr;
-}
-
-static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive)
+static u64 idedisk_read_native_max_address(ide_drive_t *drive, unsigned int lba48)
{
ide_task_t args;
struct ata_taskfile *tf = &args.tf;
@@ -360,13 +335,15 @@
memset(&args, 0, sizeof(ide_task_t));

tf->device = 0x40;
- tf->command = WIN_READ_NATIVE_MAX_EXT;
+ if (lba48) {
+ tf->command = WIN_READ_NATIVE_MAX_EXT;
+ tf->flags |= ATA_TFLAG_LBA48;
+ } else
+ tf->command = WIN_READ_NATIVE_MAX;

args.command_type = IDE_DRIVE_TASK_NO_DATA;
args.handler = &task_no_data_intr;

- tf->flags |= ATA_TFLAG_LBA48;
-
/* submit command request */
ide_raw_taskfile(drive, &args, NULL);

@@ -382,35 +359,7 @@
* Sets maximum virtual LBA address of the drive.
* Returns new maximum virtual LBA address (> 0) or 0 on failure.
*/
-static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req)
-{
- ide_task_t args;
- struct ata_taskfile *tf = &args.tf;
- unsigned long addr_set = 0;
-
- addr_req--;
- /* Create IDE/ATA command request structure */
- memset(&args, 0, sizeof(ide_task_t));
-
- tf->lbal = addr_req;
- tf->lbam = addr_req >> 8;
- tf->lbah = addr_req >> 16;
- tf->device = ((addr_req >> 24) & 0xf) | 0x40;
- tf->command = WIN_SET_MAX;
-
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.handler = &task_no_data_intr;
- /* submit command request */
- ide_raw_taskfile(drive, &args, NULL);
- /* if OK, read new maximum address value */
- if ((tf->command & 1) == 0) {
- addr_set = (u32)ide_tf_get_address(tf);
- addr_set++;
- }
- return addr_set;
-}
-
-static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req)
+static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, unsigned int lba48)
{
ide_task_t args;
struct ata_taskfile *tf = &args.tf;
@@ -423,17 +372,22 @@
tf->lbal = addr_req;
tf->lbam = addr_req >> 8;
tf->lbah = addr_req >> 16;
- tf->device = 0x40;
- tf->command = WIN_SET_MAX_EXT;
- tf->hob_lbal = addr_req >> 24;
- tf->hob_lbam = addr_req >> 32;
- tf->hob_lbah = addr_req >> 40;
+ if (lba48) {
+ tf->hob_lbal = addr_req >> 24;
+ tf->hob_lbam = addr_req >> 32;
+ tf->hob_lbah = addr_req >> 40;
+ tf->device = 0x40;
+ tf->command = WIN_SET_MAX_EXT;
+
+ tf->flags |= ATA_TFLAG_LBA48;
+ } else {
+ tf->device = ((addr_req >> 24) & 0xf) | 0x40;
+ tf->command = WIN_SET_MAX;
+ }

args.command_type = IDE_DRIVE_TASK_NO_DATA;
args.handler = &task_no_data_intr;

- tf->flags |= ATA_TFLAG_LBA48;
-
/* submit command request */
ide_raw_taskfile(drive, &args, NULL);
/* if OK, compute maximum address value */
@@ -476,10 +430,8 @@
int lba48 = idedisk_supports_lba48(drive->id);

capacity = drive->capacity64;
- if (lba48)
- set_max = idedisk_read_native_max_address_ext(drive);
- else
- set_max = idedisk_read_native_max_address(drive);
+
+ set_max = idedisk_read_native_max_address(drive, lba48);

if (set_max <= capacity)
return;
@@ -491,10 +443,8 @@
capacity, sectors_to_MB(capacity),
set_max, sectors_to_MB(set_max));

- if (lba48)
- set_max = idedisk_set_max_address_ext(drive, set_max);
- else
- set_max = idedisk_set_max_address(drive, set_max);
+ set_max = idedisk_set_max_address(drive, set_max, lba48);
+
if (set_max) {
drive->capacity64 = set_max;
printk(KERN_INFO "%s: Host Protected Area disabled.\n",


2005-02-24 16:14:34

by Greg Freemyer

[permalink] [raw]
Subject: Re: [patch ide-dev 3/9] merge LBA28 and LBA48 Host Protected Area support code

I have generic question about HPA, not the patch.

I have noticed with a SUSE 2.6.8 vendor kernel, the HPA behavior is
not consistent.

ie. With exactly the same computer/controller, but with different disk
drives (models/manufacturers) the HPA behavior varies.

In all my testing the HPA was always properly detected, but sometimes
the max_address is set to the native_max_address during bootup and
sometimes it is not.

Is there some reason for this behavior or is one case or the other a bug?

Does this patch somehow address the inconsistency?

Am I right in assuming this behavior also exists in the vanilla
kernels?. ie. I doubt that vendors are patching this behavior.

Thanks
Greg
--
Greg Freemyer


On Thu, 24 Feb 2005 15:39:51 +0100 (CET), Bartlomiej Zolnierkiewicz
<[email protected]> wrote:
>
> * merge idedisk_read_native_max_address()
> and idedisk_read_native_max_address_ext()
> * merge idedisk_set_max_address()
> and idedisk_set_max_address_ext()
>
> diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
> --- a/drivers/ide/ide-disk.c 2005-02-19 17:22:44 +01:00
> +++ b/drivers/ide/ide-disk.c 2005-02-19 17:22:44 +01:00
> @@ -325,32 +325,7 @@
> * Queries for true maximum capacity of the drive.
> * Returns maximum LBA address (> 0) of the drive, 0 if failed.
> */
> -static unsigned long idedisk_read_native_max_address(ide_drive_t *drive)
> -{
> - ide_task_t args;
> - struct ata_taskfile *tf = &args.tf;
> - unsigned long addr = 0;
> -
> - /* Create IDE/ATA command request structure */
> - memset(&args, 0, sizeof(ide_task_t));
> -
> - tf->device = 0x40;
> - tf->command = WIN_READ_NATIVE_MAX;
> -
> - args.command_type = IDE_DRIVE_TASK_NO_DATA;
> - args.handler = &task_no_data_intr;
> - /* submit command request */
> - ide_raw_taskfile(drive, &args, NULL);
> -
> - /* if OK, compute maximum address value */
> - if ((tf->command & 1) == 0) {
> - addr = (u32)ide_tf_get_address(tf);
> - addr++; /* since the return value is (maxlba - 1), we add 1 */
> - }
> - return addr;
> -}
> -
> -static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive)
> +static u64 idedisk_read_native_max_address(ide_drive_t *drive, unsigned int lba48)
> {
> ide_task_t args;
> struct ata_taskfile *tf = &args.tf;
> @@ -360,13 +335,15 @@
> memset(&args, 0, sizeof(ide_task_t));
>
> tf->device = 0x40;
> - tf->command = WIN_READ_NATIVE_MAX_EXT;
> + if (lba48) {
> + tf->command = WIN_READ_NATIVE_MAX_EXT;
> + tf->flags |= ATA_TFLAG_LBA48;
> + } else
> + tf->command = WIN_READ_NATIVE_MAX;
>
> args.command_type = IDE_DRIVE_TASK_NO_DATA;
> args.handler = &task_no_data_intr;
>
> - tf->flags |= ATA_TFLAG_LBA48;
> -
> /* submit command request */
> ide_raw_taskfile(drive, &args, NULL);
>
> @@ -382,35 +359,7 @@
> * Sets maximum virtual LBA address of the drive.
> * Returns new maximum virtual LBA address (> 0) or 0 on failure.
> */
> -static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req)
> -{
> - ide_task_t args;
> - struct ata_taskfile *tf = &args.tf;
> - unsigned long addr_set = 0;
> -
> - addr_req--;
> - /* Create IDE/ATA command request structure */
> - memset(&args, 0, sizeof(ide_task_t));
> -
> - tf->lbal = addr_req;
> - tf->lbam = addr_req >> 8;
> - tf->lbah = addr_req >> 16;
> - tf->device = ((addr_req >> 24) & 0xf) | 0x40;
> - tf->command = WIN_SET_MAX;
> -
> - args.command_type = IDE_DRIVE_TASK_NO_DATA;
> - args.handler = &task_no_data_intr;
> - /* submit command request */
> - ide_raw_taskfile(drive, &args, NULL);
> - /* if OK, read new maximum address value */
> - if ((tf->command & 1) == 0) {
> - addr_set = (u32)ide_tf_get_address(tf);
> - addr_set++;
> - }
> - return addr_set;
> -}
> -
> -static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req)
> +static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, unsigned int lba48)
> {
> ide_task_t args;
> struct ata_taskfile *tf = &args.tf;
> @@ -423,17 +372,22 @@
> tf->lbal = addr_req;
> tf->lbam = addr_req >> 8;
> tf->lbah = addr_req >> 16;
> - tf->device = 0x40;
> - tf->command = WIN_SET_MAX_EXT;
> - tf->hob_lbal = addr_req >> 24;
> - tf->hob_lbam = addr_req >> 32;
> - tf->hob_lbah = addr_req >> 40;
> + if (lba48) {
> + tf->hob_lbal = addr_req >> 24;
> + tf->hob_lbam = addr_req >> 32;
> + tf->hob_lbah = addr_req >> 40;
> + tf->device = 0x40;
> + tf->command = WIN_SET_MAX_EXT;
> +
> + tf->flags |= ATA_TFLAG_LBA48;
> + } else {
> + tf->device = ((addr_req >> 24) & 0xf) | 0x40;
> + tf->command = WIN_SET_MAX;
> + }
>
> args.command_type = IDE_DRIVE_TASK_NO_DATA;
> args.handler = &task_no_data_intr;
>
> - tf->flags |= ATA_TFLAG_LBA48;
> -
> /* submit command request */
> ide_raw_taskfile(drive, &args, NULL);
> /* if OK, compute maximum address value */
> @@ -476,10 +430,8 @@
> int lba48 = idedisk_supports_lba48(drive->id);
>
> capacity = drive->capacity64;
> - if (lba48)
> - set_max = idedisk_read_native_max_address_ext(drive);
> - else
> - set_max = idedisk_read_native_max_address(drive);
> +
> + set_max = idedisk_read_native_max_address(drive, lba48);
>
> if (set_max <= capacity)
> return;
> @@ -491,10 +443,8 @@
> capacity, sectors_to_MB(capacity),
> set_max, sectors_to_MB(set_max));
>
> - if (lba48)
> - set_max = idedisk_set_max_address_ext(drive, set_max);
> - else
> - set_max = idedisk_set_max_address(drive, set_max);
> + set_max = idedisk_set_max_address(drive, set_max, lba48);
> +
> if (set_max) {
> drive->capacity64 = set_max;
> printk(KERN_INFO "%s: Host Protected Area disabled.\n",
> -
> To unsubscribe from this list: send the line "unsubscribe linux-ide" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>

Subject: Re: [patch ide-dev 3/9] merge LBA28 and LBA48 Host Protected Area support code

On Thursday 24 February 2005 17:10, Greg Freemyer wrote:
> I have generic question about HPA, not the patch.
>
> I have noticed with a SUSE 2.6.8 vendor kernel, the HPA behavior is
> not consistent.

Please retry with vanilla kernel.

> ie. With exactly the same computer/controller, but with different disk
> drives (models/manufacturers) the HPA behavior varies.
>
> In all my testing the HPA was always properly detected, but sometimes
> the max_address is set to the native_max_address during bootup and
> sometimes it is not.

Please be more precise.

What do you mean by 'sometimes'?

What are the exact differences between machines?

Are there any differences in software configurations
(i.e. kernel parameters) between this machines?

> Is there some reason for this behavior or is one case or the other a bug?

Dunno, not enough info.

> Does this patch somehow address the inconsistency?

No.

> Am I right in assuming this behavior also exists in the vanilla
> kernels?. ie. I doubt that vendors are patching this behavior.

Recent vanilla kernels always set maximum available capacity.

2005-02-24 20:20:04

by Greg Freemyer

[permalink] [raw]
Subject: Re: [patch ide-dev 3/9] merge LBA28 and LBA48 Host Protected Area support code

On Thu, 24 Feb 2005 17:30:55 +0100, Bartlomiej Zolnierkiewicz
<[email protected]> wrote:
> On Thursday 24 February 2005 17:10, Greg Freemyer wrote:
> > I have generic question about HPA, not the patch.
> >
> > I have noticed with a SUSE 2.6.8 vendor kernel, the HPA behavior is
> > not consistent.
>
> Please retry with vanilla kernel.
>
Will do. I assume 2.6.10 is fine?

> > ie. With exactly the same computer/controller, but with different disk
> > drives (models/manufacturers) the HPA behavior varies.
> >
> > In all my testing the HPA was always properly detected, but sometimes
> > the max_address is set to the native_max_address during bootup and
> > sometimes it is not.
>
> Please be more precise.
>
> What do you mean by 'sometimes'?
>
Seems to be disk drive specific.

For instance my records show that for a:
Maxtor model 32049h2
20 GB
Manufactured Mar. 2001
drive I was working with last week the maximum available capacity was
set to the native max. At power on the max. avail. was slightly
smaller than native max.

With exactly the same computer I just tested a HPA test drive of mine:
Hitachi Deskstar
model HDS728080PLAT20
82.3 GB (per label)
Manufactured Oct. 2004
and the max. avail. was not reset. From boot.msg

<6>hdc: max request size: 1024KiB
<6>hdc: Host Protected Area detected.
<4> current capacity is 50001 sectors (25 MB)
<4> native capacity is 160836480 sectors (82348 MB)
<4>hdc: task_no_data_intr: status=0x51 { DriveReady SeekComplete Error }
<4>hdc: task_no_data_intr: error=0x04 { DriveStatusError }
<4>ide: failed opcode was: 0x37
<6>hdc: 50001 sectors (25 MB) w/1719KiB Cache, CHS=49/255/63, UDMA(100)
<7>hdc: cache flushes supported
<6> hdc: hdc1

Looking in /proc/ide/hdc/capacity after boot I show 50001 sectors.

Note this is still with the SUSE 2.6.8 vendor kernel and I don't know
what the Drive errors are, but they seem to be a driver issue, not a
hardware issue. Concievably they are related to the behavior, but I
don't know.

> What are the exact differences between machines?
>
Same machine / OS, just connecting different drives. By chance, the
machine had been powered off between the 2 tests. (It is a portable
machine that is normally locked away when not in use.)

> Are there any differences in software configurations
> (i.e. kernel parameters) between this machines?
>
no

> > Is there some reason for this behavior or is one case or the other a bug?
>
> Dunno, not enough info.
>
> > Does this patch somehow address the inconsistency?
>
> No.
>
> > Am I right in assuming this behavior also exists in the vanilla
> > kernels?. ie. I doubt that vendors are patching this behavior.
>
> Recent vanilla kernels always set maximum available capacity.
>
Was 2.6.8 recent enough to have this behavior?

Greg
--
Greg Freemyer

2005-02-25 21:39:11

by Greg Freemyer

[permalink] [raw]
Subject: Re: [patch ide-dev 3/9] merge LBA28 and LBA48 Host Protected Area support code

Retested with Hitachi drive and 2.6.10 vanilla kernel.

Same behavior, HPA is not reset to native max.

Greg
--
Greg Freemyer

On Thu, 24 Feb 2005 15:19:52 -0500, Greg Freemyer
<[email protected]> wrote:
> On Thu, 24 Feb 2005 17:30:55 +0100, Bartlomiej Zolnierkiewicz
> <[email protected]> wrote:
> > On Thursday 24 February 2005 17:10, Greg Freemyer wrote:
> > > I have generic question about HPA, not the patch.
> > >
> > > I have noticed with a SUSE 2.6.8 vendor kernel, the HPA behavior is
> > > not consistent.
> >
> > Please retry with vanilla kernel.
> >
> Will do. I assume 2.6.10 is fine?
>
> > > ie. With exactly the same computer/controller, but with different disk
> > > drives (models/manufacturers) the HPA behavior varies.
> > >
> > > In all my testing the HPA was always properly detected, but sometimes
> > > the max_address is set to the native_max_address during bootup and
> > > sometimes it is not.
> >
> > Please be more precise.
> >
> > What do you mean by 'sometimes'?
> >
> Seems to be disk drive specific.
>
> For instance my records show that for a:
> Maxtor model 32049h2
> 20 GB
> Manufactured Mar. 2001
> drive I was working with last week the maximum available capacity was
> set to the native max. At power on the max. avail. was slightly
> smaller than native max.
>
> With exactly the same computer I just tested a HPA test drive of mine:
> Hitachi Deskstar
> model HDS728080PLAT20
> 82.3 GB (per label)
> Manufactured Oct. 2004
> and the max. avail. was not reset. From boot.msg
>
> <6>hdc: max request size: 1024KiB
> <6>hdc: Host Protected Area detected.
> <4> current capacity is 50001 sectors (25 MB)
> <4> native capacity is 160836480 sectors (82348 MB)
> <4>hdc: task_no_data_intr: status=0x51 { DriveReady SeekComplete Error }
> <4>hdc: task_no_data_intr: error=0x04 { DriveStatusError }
> <4>ide: failed opcode was: 0x37
> <6>hdc: 50001 sectors (25 MB) w/1719KiB Cache, CHS=49/255/63, UDMA(100)
> <7>hdc: cache flushes supported
> <6> hdc: hdc1
>
> Looking in /proc/ide/hdc/capacity after boot I show 50001 sectors.
>
> Note this is still with the SUSE 2.6.8 vendor kernel and I don't know
> what the Drive errors are, but they seem to be a driver issue, not a
> hardware issue. Concievably they are related to the behavior, but I
> don't know.
>
> > What are the exact differences between machines?
> >
> Same machine / OS, just connecting different drives. By chance, the
> machine had been powered off between the 2 tests. (It is a portable
> machine that is normally locked away when not in use.)
>
> > Are there any differences in software configurations
> > (i.e. kernel parameters) between this machines?
> >
> no
>
> > > Is there some reason for this behavior or is one case or the other a bug?
> >
> > Dunno, not enough info.
> >
> > > Does this patch somehow address the inconsistency?
> >
> > No.
> >
> > > Am I right in assuming this behavior also exists in the vanilla
> > > kernels?. ie. I doubt that vendors are patching this behavior.
> >
> > Recent vanilla kernels always set maximum available capacity.
> >
> Was 2.6.8 recent enough to have this behavior?
>
> Greg
> --
> Greg Freemyer
>