Messages in this thread Patch in this message | | | Date | Fri, 28 Dec 2001 01:06:25 +0100 (CET) | From | Eric Lammerts <> | Subject | [PATCH] Re: 2.4.x kernels, big ide disks and old bios |
| |
On Fri, 28 Dec 2001, Stephan von Krawczynski wrote: > I must admit I have still not had a look at it, but on the other hand: > if it makes big IDE drives work on old mobo & bios, it may be a good > idea to include its intelligence into the kernel, or not?
I cleaned up the patch a bit (see below). It now performs the SET_MAX command only when needed, and is far less verbose (only prints 1 line when unclipping). It applies against 2.4.18pre1 and 2.5.2pre2.
I've tested it with a Maxtor 96147U8 (60Gb), Maxtor 98196H8 (80Gb) and WDC WD300BB (30Gb) (the last one just for testing, and I had to use ibmsetmax instead of setmax to make the drive remember it). It also worked with some 2.5" IBM hdd a while back (don't remember the exact model).
Jens, please consider this patch for inclusion into 2.4 and/or 2.5. (or should I talk to someone else?)
Eric
--- 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) - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |