From: Andries.Brouwer@cwi.nl
To: B.Zolnierkiewicz@elka.pw.edu.pl, aebr@win.tue.nl
Cc: alan@lxorguk.ukuu.org.uk, andersen@codepoet.org,
linux-kernel@vger.kernel.org, marcelo@conectiva.com.br
Subject: Re: [PATCH] ide-disk.c rev 1.13 killed CONFIG_IDEDISK_STROKE
Date: Thu, 7 Aug 2003 03:59:56 +0200 (MEST) [thread overview]
Message-ID: <UTC200308070159.h771xup04247.aeb@smtp.cwi.nl> (raw)
From aebr@win.tue.nl Thu Aug 7 03:54:02 2003
Ha - and you didnt even tell me you had this patch out.
Looks good.
[will try to find the appropriate fragment of my patch again
for comparison purposes]
Here it is:
diff -u --recursive --new-file -X /linux/dontdiff a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
--- a/drivers/ide/ide-disk.c Wed Aug 6 23:02:38 2003
+++ b/drivers/ide/ide-disk.c Thu Aug 7 04:49:18 2003
@@ -85,11 +85,6 @@
{
unsigned long lba_sects, chs_sects, head, tail;
- if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)) {
- printk("48-bit Drive: %llu \n", id->lba_capacity_2);
- return 1;
- }
-
/*
* The ATA spec tells large drives to return
* C/H/S = 16383/16/63 independent of their size.
@@ -811,7 +806,7 @@
} else {
u8 cur = hwif->INB(IDE_SELECT_REG);
if (cur & 0x40) { /* using LBA? */
- printk(", LBAsect=%ld", (unsigned long)
+ printk(", LBAsect=%lu", (unsigned long)
((cur&0xf)<<24)
|(hwif->INB(IDE_HCYL_REG)<<16)
|(hwif->INB(IDE_LCYL_REG)<<8)
@@ -981,8 +976,8 @@
args.tfRegister[IDE_SELECT_OFFSET] = 0x40;
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX_EXT;
args.command_type = ide_cmd_type_parser(&args);
- /* submit command request */
- ide_raw_taskfile(drive, &args, NULL);
+ /* submit command request */
+ ide_raw_taskfile(drive, &args, NULL);
/* if OK, compute maximum address value */
if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
@@ -1002,6 +997,8 @@
/*
* Sets maximum virtual LBA address of the drive.
* Returns new maximum virtual LBA address (> 0) or 0 on failure.
+ *
+ * Must be immediately preceded by read_native_max.
*/
static unsigned long
idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req)
@@ -1031,6 +1028,7 @@
return addr_set;
}
+/* Note: must be immediately preceded by read_native_max_ext */
static unsigned long long
idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req)
{
@@ -1071,114 +1069,153 @@
static unsigned long long
sectors_to_MB(unsigned long long n) {
- n <<= 9; /* make it bytes */
- do_div(n, 1000000); /* make it MB */
+ n <<= 9; /* make it bytes */
+ do_div(n, 1000000); /* make it MB */
return n;
}
+static inline int
+idedisk_supports_lba(const struct hd_driveid *id)
+{
+ return (id->capability & 2);
+}
+
/*
- * Tests if the drive supports Host Protected Area feature.
- * Returns true if supported, false otherwise.
+ * Bits 10 of command_set_1 and cfs_enable_1 must be equal,
+ * so on non-buggy drives we need test only one.
+ * However, we should also check whether these fields are valid.
*/
-static inline int idedisk_supports_host_protected_area(ide_drive_t *drive)
+static inline int
+idedisk_supports_host_protected_area(const struct hd_driveid *id)
{
- int flag = (drive->id->cfs_enable_1 & 0x0400) ? 1 : 0;
- if (flag)
- printk(KERN_INFO "%s: host protected area => %d\n", drive->name, flag);
- return flag;
+ return (id->command_set_1 & 0x0400) && (id->cfs_enable_1 & 0x0400);
}
/*
- * Compute drive->capacity, the full capacity of the drive
- * Called with drive->id != NULL.
- *
- * To compute capacity, this uses either of
- *
- * 1. CHS value set by user (whatever user sets will be trusted)
- * 2. LBA value from target drive (require new ATA feature)
- * 3. LBA value from system BIOS (new one is OK, old one may break)
- * 4. CHS value from system BIOS (traditional style)
- *
- * in above order (i.e., if value of higher priority is available,
- * reset will be ignored).
+ * The same here.
*/
-#define IDE_STROKE_LIMIT (32000*1024*2)
-static void init_idedisk_capacity (ide_drive_t *drive)
+static inline int
+idedisk_supports_lba48(const struct hd_driveid *id)
{
- struct hd_driveid *id = drive->id;
- unsigned long capacity = drive->cyl * drive->head * drive->sect;
- unsigned long set_max = idedisk_read_native_max_address(drive);
- unsigned long long capacity_2 = capacity;
- unsigned long long set_max_ext;
-
- drive->capacity48 = 0;
- drive->select.b.lba = 0;
+ return (id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400);
+}
- (void) idedisk_supports_host_protected_area(drive);
+static inline unsigned long long
+lba48_capacity(const struct hd_driveid *id)
+{
+ return id->lba_capacity_2;
+}
- if (id->cfs_enable_2 & 0x0400) {
- capacity_2 = id->lba_capacity_2;
- drive->head = drive->bios_head = 255;
- drive->sect = drive->bios_sect = 63;
- drive->cyl = (unsigned int) capacity_2 / (drive->head * drive->sect);
- drive->select.b.lba = 1;
- set_max_ext = idedisk_read_native_max_address_ext(drive);
- if (set_max_ext > capacity_2 && capacity_2 > IDE_STROKE_LIMIT) {
+/*
+ * See whether some part of the disk was set off as Host Protected Area.
+ * If so, report this, and possible enable access to it.
+ */
+static void
+do_add_hpa(ide_drive_t *drive) {
+ unsigned int capacity;
+ unsigned long set_max;
+
+ capacity = drive->capacity;
+ set_max = idedisk_read_native_max_address(drive);
+
+ if (set_max > capacity) {
+ /* Report */
+ printk(KERN_INFO "%s: Host Protected Area detected.\n"
+ " current capacity is %u sectors (%u MB)\n"
+ " native capacity is %lu sectors (%lu MB)\n",
+ drive->name, capacity,
+ (capacity - capacity/625 + 974)/1950,
+ set_max, (set_max - set_max/625 + 974)/1950);
#ifdef CONFIG_IDEDISK_STROKE
- set_max_ext = idedisk_read_native_max_address_ext(drive);
- set_max_ext = idedisk_set_max_address_ext(drive, set_max_ext);
- if (set_max_ext) {
- drive->capacity48 = capacity_2 = set_max_ext;
- drive->cyl = (unsigned int) set_max_ext / (drive->head * drive->sect);
- drive->select.b.lba = 1;
- drive->id->lba_capacity_2 = capacity_2;
- }
-#else /* !CONFIG_IDEDISK_STROKE */
- printk(KERN_INFO "%s: setmax_ext LBA %llu, native %llu\n",
- drive->name, set_max_ext, capacity_2);
-#endif /* CONFIG_IDEDISK_STROKE */
+ /* Raise limit */
+ set_max = idedisk_set_max_address(drive, set_max);
+ if (set_max) {
+ drive->capacity = set_max;
+ printk(KERN_INFO "%s: Host Protected Area Disabled\n",
+ drive->name);
}
- drive->cyl = (unsigned int) capacity_2 / (drive->head * drive->sect);
- drive->bios_cyl = drive->cyl;
- drive->capacity48 = capacity_2;
- drive->capacity = (unsigned long) capacity_2;
- return;
- /* Determine capacity, and use LBA if the drive properly supports it */
- } else if ((id->capability & 2) && lba_capacity_is_ok(id)) {
- capacity = id->lba_capacity;
- drive->cyl = capacity / (drive->head * drive->sect);
- drive->select.b.lba = 1;
+#endif
}
+}
+
+static void
+do_add_hpa48(ide_drive_t *drive) {
+ unsigned long long set_max_ext;
- if (set_max > capacity && capacity > IDE_STROKE_LIMIT) {
+ set_max_ext = idedisk_read_native_max_address_ext(drive);
+ if (set_max_ext > drive->capacity48) {
+ unsigned long long nativeMB, currentMB;
+
+ /* Report on additional space */
+ nativeMB = sectors_to_MB(set_max_ext);
+ currentMB = sectors_to_MB(drive->capacity48);
+ printk(KERN_INFO
+ "%s: Host Protected Area detected.\n"
+ " current capacity is %llu sectors (%llu MB)\n"
+ " native capacity is %llu sectors (%llu MB)\n",
+ drive->name, drive->capacity48, currentMB,
+ set_max_ext, nativeMB);
#ifdef CONFIG_IDEDISK_STROKE
- set_max = idedisk_read_native_max_address(drive);
- set_max = idedisk_set_max_address(drive, set_max);
- if (set_max) {
- drive->capacity = capacity = set_max;
- drive->cyl = set_max / (drive->head * drive->sect);
- drive->select.b.lba = 1;
- drive->id->lba_capacity = capacity;
- }
-#else /* !CONFIG_IDEDISK_STROKE */
- printk(KERN_INFO "%s: setmax LBA %lu, native %lu\n",
- drive->name, set_max, capacity);
-#endif /* CONFIG_IDEDISK_STROKE */
+ /* Raise limit */
+ set_max_ext = idedisk_set_max_address_ext(drive, set_max_ext);
+ if (set_max_ext) {
+ drive->capacity48 = set_max_ext;
+ printk(KERN_INFO
+ "%s: Host Protected Area Disabled\n",
+ drive->name);
+ }
+#endif
}
+}
- drive->capacity = capacity;
+/*
+ * Compute drive->capacity, the amount accessible with CHS/LBA commands,
+ * and drive->capacity48, the amount accessible with LBA48 commands.
+ * Also sets drive->select.b.lba.
+ *
+ * Called with drive->id != NULL.
+ */
+static void init_idedisk_capacity(ide_drive_t *drive)
+{
+ struct hd_driveid *id;
+ unsigned long capacity;
+ unsigned long long capacity48;
+
+ id = drive->id;
+
+ if (idedisk_supports_lba48(id)) {
+ /* drive speaks 48-bit LBA */
+ drive->capacity48 = capacity48 = lba48_capacity(id);
+ capacity = capacity48; /* truncate to 32 bits */
+ if (capacity == capacity48)
+ drive->capacity = capacity;
+ else
+ drive->capacity = 0xffffffff;
+ drive->select.b.lba = 1;
+ } else if (idedisk_supports_lba(id) && lba_capacity_is_ok(id)) {
+ /* drive speaks 28-bit LBA */
+ drive->capacity = capacity = id->lba_capacity;
+ drive->capacity48 = 0;
+ drive->select.b.lba = 1;
+ } else {
+ /* drive speaks CHS only */
+ capacity = drive->cyl * drive->head * drive->sect;
+ drive->capacity = capacity;
+ drive->capacity48 = 0;
+ drive->select.b.lba = 0;
+ }
- if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)) {
- drive->capacity48 = id->lba_capacity_2;
- drive->head = 255;
- drive->sect = 63;
- drive->cyl = (unsigned long)(drive->capacity48) / (drive->head * drive->sect);
+ if (idedisk_supports_host_protected_area(id)) {
+ if (idedisk_supports_lba48(id))
+ do_add_hpa48(drive);
+ else
+ do_add_hpa(drive);
}
}
static sector_t idedisk_capacity (ide_drive_t *drive)
{
- if (drive->id->cfs_enable_2 & 0x0400)
+ if (idedisk_supports_lba48(drive->id))
return (drive->capacity48 - drive->sect0);
return (drive->capacity - drive->sect0);
}
@@ -1469,7 +1506,7 @@
if (HWIF(drive)->addressing)
return 0;
- if (!(drive->id->cfs_enable_2 & 0x0400))
+ if (!idedisk_supports_lba48(drive->id))
return -EIO;
drive->addressing = arg;
return 0;
@@ -1639,19 +1676,29 @@
* by correcting bios_cyls:
*/
capacity = idedisk_capacity (drive);
- if (!drive->forced_geom && drive->bios_sect && drive->bios_head) {
- unsigned int cap0 = capacity; /* truncate to 32 bits */
- unsigned int cylsz, cyl;
-
- if (cap0 != capacity)
- drive->bios_cyl = 65535;
- else {
- cylsz = drive->bios_sect * drive->bios_head;
- cyl = cap0 / cylsz;
- if (cyl > 65535)
- cyl = 65535;
- if (cyl > drive->bios_cyl)
- drive->bios_cyl = cyl;
+ if (!drive->forced_geom) {
+ int lba48 = idedisk_supports_lba48(id);
+
+ if (lba48) {
+ /* compatibility */
+ drive->bios_sect = 63;
+ drive->bios_head = 255;
+ }
+
+ if (drive->bios_sect && drive->bios_head) {
+ unsigned int cap0 = capacity; /* truncate to 32 bits */
+ unsigned int cylsz, cyl;
+
+ if (cap0 != capacity)
+ drive->bios_cyl = 65535;
+ else {
+ cylsz = drive->bios_sect * drive->bios_head;
+ cyl = cap0 / cylsz;
+ if (cyl > 65535)
+ cyl = 65535;
+ if (cyl > drive->bios_cyl || lba48)
+ drive->bios_cyl = cyl;
+ }
}
}
printk(KERN_INFO "%s: %llu sectors (%llu MB)",
next reply other threads:[~2003-08-07 2:00 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-08-07 1:59 Andries.Brouwer [this message]
-- strict thread matches above, loose matches on Subject: below --
2003-08-07 13:22 Andries.Brouwer
2003-08-07 13:50 ` Bartlomiej Zolnierkiewicz
2003-08-07 11:23 Andries.Brouwer
2003-08-07 11:49 ` Bartlomiej Zolnierkiewicz
2003-08-07 9:57 Andries.Brouwer
2003-08-07 10:44 ` Bartlomiej Zolnierkiewicz
[not found] <20030806181142.GD25910@codepoet.org>
2003-08-06 18:32 ` Bartlomiej Zolnierkiewicz
2003-08-06 19:30 ` Erik Andersen
2003-08-06 19:58 ` Bartlomiej Zolnierkiewicz
2003-08-07 1:11 ` Andries Brouwer
2003-08-07 2:31 ` Bartlomiej Zolnierkiewicz
2003-08-02 12:45 Andries Brouwer
2003-08-02 13:10 ` Bartlomiej Zolnierkiewicz
2003-08-02 17:42 ` Andries Brouwer
2003-08-02 21:06 ` Alan Cox
2003-08-02 23:34 ` [PATCH] " Erik Andersen
2003-08-03 1:26 ` Andries Brouwer
2003-08-03 2:12 ` Erik Andersen
2003-08-03 9:52 ` Jens Axboe
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=UTC200308070159.h771xup04247.aeb@smtp.cwi.nl \
--to=andries.brouwer@cwi.nl \
--cc=B.Zolnierkiewicz@elka.pw.edu.pl \
--cc=aebr@win.tue.nl \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=andersen@codepoet.org \
--cc=linux-kernel@vger.kernel.org \
--cc=marcelo@conectiva.com.br \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®