Below is the important part (either my SVN client or OW's text editor seems to do some tab/space conversion) based on the patch Eric posted based on RayeR's changes.
I changed where the +1 to cylinders was done and I want some comments because I'm trying to make sure the code is consistent. The prior patches explicitly added 1 to driveParam->chs.Cylinder at various places, but if I read the code and int 13h calls correctly, this should actually be done when we extract the data from the int13h/08 call as what we really want here is a count not a maximum value to use -- where heads and cylinders use a value in range of 0 to (count-1) and sectors uses a range of 1 to count. The LBA call returns count for C/H/S which we store directly, and we store directly the count for H/S in the CHS form, but shouldn't we be storing C as count here as well? that is what the below patch does. This will not effect the LBA<-->CHS translation as our LBA_to_CHS() does not use driveParam->chs.Cylinder as part of the conversion. Please review and let me know if I am overlooking something, which I easily could. This gets confusing since C/H/S gets used to mean current, max value, or total - cylinder, head, sector to access which uses ranges starting at 0 for cylinder and head and 1 for sector but with a max value for cylinder and head determined by interface we are accessing (BIOS interface limits heads value to 255 (256 total heads), but apparently? older DOSes had issues so generally limited to to 255 total heads (max value 254) whereas limit on heads to device for direct access should be 16 (max value 15) -- then cylinders have similar restrictions BIOS interface limits to 1024 total cylinders (1023 max value) and direct access to device limits to 65536 total cylinders (65535=0xFFFF max value) and both support 1 to 63 for sectors). And then when using LBA<-->LCHS it is recommended to use total heads=255 (max value 254) with sectors=63 [to avoid translation errors if moved to different BIOS]. Which leads to confusion if context not clear - does CHS=1023/255/63 mean accessing cylinder 1023, max value of 1023 corresponding to 1024th cylinder, or only 1023 total cylinders ... Thanks, Jeremy Index: initdisk.c =================================================================== --- initdisk.c (revision 1372) +++ initdisk.c (working copy) @@ -339,7 +339,22 @@ /* translate LBA sectors into CHS addressing - copied and pasted from dsk.c! + initially copied and pasted from dsk.c! + + LBA to/from CHS conversion - see http://www.ata-atapi.com/ How It Works section on CHSxlat - CHS Translation + LBA (logical block address) simple 0 to N-1 used internally and with extended int 13h (BIOS) + L-CHS (logical CHS) is the CHS view when using int 13h (BIOS) + P-CHS (physical CHS) is the CHS view when directly accessing disk, should not, but could be used in BS or MBR + + LBA = ( (cylinder * heads_per_cylinder + heads ) * sectors_per_track ) + sector - 1 + + cylinder = LBA / (heads_per_cylinder * sectors_per_track) + temp = LBA % (heads_per_cylinder * sectors_per_track) + head = temp / sectors_per_track + sector = temp % sectors_per_track + 1 + + where heads_per_cylinder and sectors_per_track are the current translation mode values. + cyclinder and heads are 0 to N-1 based, sector is 1 to N based */ void init_LBA_to_CHS(struct CHS *chs, ULONG LBA_address, @@ -747,9 +762,11 @@ if (regs.flags & 0x01) goto ErrorReturn; - driveParam->chs.Head = (regs.d.x >> 8) + 1; - driveParam->chs.Sector = (regs.c.x & 0x3f); - driveParam->chs.Cylinder = (regs.c.x >> 8) | ((regs.c.x & 0xc0) << 2); + /* int13h call returns max value, store as count (#) i.e. +1 for 0 based heads & cylinders */ + driveParam->chs.Head = (regs.d.x >> 8) + 1; /* DH = max head value = # of heads - 1 (0-255) */ + driveParam->chs.Sector = (regs.c.x & 0x3f); /* CL bits 0-5 = max sector value = # (sectors/track) - 1 (1-63) */ + /* max cylinder value = # cylinders - 1 (0-1023) = [high two bits]CL7:6=cyls9:8, [low byte]CH=cyls7:0 */ + driveParam->chs.Cylinder = (regs.c.x >> 8) | ((regs.c.x & 0xc0) << 2) + 1; if (driveParam->chs.Sector == 0) { /* happens e.g. with Bochs 1.x if no harddisk defined */ @@ -760,13 +777,13 @@ if (!(driveParam->descflags & DF_LBA)) { driveParam->total_sectors = - min(driveParam->chs.Cylinder, 1023) + (ULONG)driveParam->chs.Cylinder * driveParam->chs.Head * driveParam->chs.Sector; } driveParam->driveno = drive; - DebugPrintf(("drive parameters %02x - %04lu-%u-%u", + DebugPrintf(((("drive %02Xh - total C = %u, H = %u, S = %u,", drive, driveParam->chs.Cylinder, driveParam->chs.Head, driveParam->chs.Sector)); ------------------------------------------------------------------------------ The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your production scanning environment may not be a perfect world - but thanks to Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700 Series Scanner you'll get full speed at 300 dpi even with all image processing features enabled. http://p.sf.net/sfu/kodak-com _______________________________________________ Freedos-kernel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/freedos-kernel
