--- linux/drivers/ide/ide-disk.c.orig	Thu Dec 27 22:19:11 2001
+++ linux/drivers/ide/ide-disk.c	Fri Dec 28 00:37:36 2001
@@ -500,6 +500,78 @@
 			current_capacity(drive));
 }
 
+
+/*
+ * Queries for true maximum capacity of the drive and (if needed) sets
+ * maximum virtual LBA address accordingly. Also updates drive->*
+ * settings.
+ */
+static void idedisk_unclip(ide_drive_t *drive)
+{
+	byte args[7];
+	unsigned long addr = 0;
+
+	if(!(drive->id->command_set_1 & 0x0400)) {
+		/* drive does not support Host Protected Area feature. */
+		return;
+	}
+
+	/* create IDE/ATA command request structure */
+	args[0] = 0xf8; /* READ_NATIVE_MAX - see ATA spec */
+	args[IDE_FEATURE_OFFSET] = 0x00;
+	args[IDE_NSECTOR_OFFSET] = 0x00;
+	args[IDE_SECTOR_OFFSET] = 0x00;
+	args[IDE_LCYL_OFFSET] = 0x00;
+	args[IDE_HCYL_OFFSET] = 0x00;
+	args[IDE_SELECT_OFFSET] = 0x40;
+
+	if(ide_wait_cmd_task(drive, args) != 0 || (args[0] & 0x01) != 0) {
+		/* silently ignore failed command */
+		return;
+	}
+	
+	/* read max LBA value */
+	addr = ((args[IDE_SELECT_OFFSET] & 0x0f) << 24) | 
+	       (args[IDE_HCYL_OFFSET] << 16) |
+	       (args[IDE_LCYL_OFFSET] << 8) |
+	       (args[IDE_SECTOR_OFFSET]);
+	
+	/* sanity check */
+	if(addr == 0) return;
+
+	if(drive->capacity == (addr + 1)) {
+		/* no unclipping needed */
+		return;
+	}
+
+	printk("%s: unclipping drive from %lu sectors to %lu sectors\n",
+		drive->name, drive->capacity, addr + 1);
+
+	/* create IDE/ATA command request structure */
+	args[0] = 0xf9; /* SET_MAX - see ATA spec */
+	args[IDE_FEATURE_OFFSET] = 0x00;
+	args[IDE_NSECTOR_OFFSET] = 0x00;
+	args[IDE_SECTOR_OFFSET] = addr & 0xff;
+	args[IDE_LCYL_OFFSET] = (addr >> 8) & 0xff;
+	args[IDE_HCYL_OFFSET] = (addr >> 16) & 0xff;
+	args[IDE_SELECT_OFFSET] = ((addr >> 24) & 0x0f) | 0x40;
+
+	/* submit command request - if OK, read new max LBA value */
+	if(ide_wait_cmd_task(drive, args) == 0 && (args[0] & 0x01) == 0) {
+		addr = ((args[IDE_SELECT_OFFSET] & 0x0f) << 24) |
+		       (args[IDE_HCYL_OFFSET] << 16) |
+		       (args[IDE_LCYL_OFFSET] << 8) |
+		       (args[IDE_SECTOR_OFFSET]);
+
+		drive->select.b.lba = 1;
+		drive->capacity = addr + 1;
+		drive->cyl = drive->capacity / (drive->head * drive->sect);
+	} else {
+		printk("%s: unclipping drive failed\n", drive->name);
+	}
+}
+
+
 /*
  * Compute drive->capacity, the full capacity of the drive
  * Called with drive->id != NULL.
@@ -518,6 +590,8 @@
 		drive->select.b.lba = 1;
 	}
 	drive->capacity = capacity;
+
+	idedisk_unclip(drive);
 }
 
 static unsigned long idedisk_capacity (ide_drive_t  *drive)
