Ignore:
Timestamp:
Aug 9, 2013, 12:17:15 AM (12 years ago)
Author:
David Azarewicz
Message:

Added a check for bad geometries reported by the BIOS and fix them.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/os2ahci/ata.c

    r165 r169  
    440440
    441441  return(rc);
     442}
     443
     444/* Adjust the cylinder count in the physical
     445 * geometry to the last full cylinder.
     446 */
     447int adjust_cylinders(GEOMETRY _far *geometry, ULONG TotalSectors) {
     448  USHORT SecPerCyl;
     449  int rc = FALSE;
     450
     451  geometry->TotalSectors = TotalSectors;
     452  SecPerCyl = geometry->SectorsPerTrack * geometry->NumHeads;
     453  if (SecPerCyl > 0) {
     454    ULONG TotalCylinders  = TotalSectors / SecPerCyl;
     455
     456    geometry->TotalSectors   = TotalCylinders * SecPerCyl;
     457    geometry->TotalCylinders = TotalCylinders;
     458    if (TotalCylinders >> 16) {
     459      geometry->TotalCylinders = 65535;
     460      rc = TRUE;
     461    }
     462  }
     463  return (rc);
     464}
     465
     466/* Calculate the logical geometry based on the input physcial geometry
     467 * using the LBA Assist Translation algorithm.
     468 */
     469#define BIOS_MAX_CYLINDERS       1024l
     470#define BIOS_MAX_NUMHEADS         255
     471#define BIOS_MAX_SECTORSPERTRACK   63
     472void log_geom_calculate_LBA_assist(GEOMETRY _far *geometry, ULONG TotalSectors)
     473{
     474  UCHAR numSpT   = BIOS_MAX_SECTORSPERTRACK;
     475  UCHAR numHeads = BIOS_MAX_NUMHEADS;
     476  ULONG Cylinders;
     477
     478  if (TotalSectors <= (BIOS_MAX_CYLINDERS * 128 * BIOS_MAX_SECTORSPERTRACK)) {
     479    USHORT temp = (TotalSectors - 1) / (BIOS_MAX_CYLINDERS * BIOS_MAX_SECTORSPERTRACK);
     480
     481    if (temp < 16)      numHeads = 16;
     482    else if (temp < 32) numHeads = 32;
     483    else if (temp < 64) numHeads = 64;
     484    else                numHeads = 128;
     485  }
     486
     487  do {
     488    Cylinders = TotalSectors / (USHORT)(numHeads * numSpT);
     489    if (Cylinders >> 16) {
     490      if (numSpT < 128)
     491        numSpT = (numSpT << 1) | 1;
     492      else
     493        Cylinders = 65535; // overflow !
     494    }
     495  } while (Cylinders >> 16);
     496
     497  geometry->TotalCylinders  = Cylinders;
     498  geometry->NumHeads        = numHeads;
     499  geometry->SectorsPerTrack = numSpT;
    442500}
    443501
     
    574632    geometry->NumHeads        = 255;
    575633    geometry->SectorsPerTrack = track_size[a][p];
    576     geometry->TotalCylinders  = geometry->TotalSectors /
    577                                  ((u32) geometry->NumHeads *
    578                                   (u32) geometry->SectorsPerTrack);
     634    geometry->TotalCylinders  = geometry->TotalSectors / ((u32) geometry->NumHeads * (u32) geometry->SectorsPerTrack);
    579635    Method = "Custom";
    580   } else if (CUR_HEADS(id_buf) > 0 && CUR_CYLS(id_buf) > 0 &&
    581              CUR_SECTORS(id_buf) > 0 &&
    582              CUR_CAPACITY(id_buf) == (u32) CUR_HEADS(id_buf) *
    583                                      (u32) CUR_CYLS(id_buf) *
    584                                      (u32) CUR_SECTORS(id_buf)) {
     636  } else if (CUR_HEADS(id_buf) > 0 && CUR_CYLS(id_buf) > 0 && CUR_SECTORS(id_buf) > 0 &&
     637             CUR_CAPACITY(id_buf) == (u32) CUR_HEADS(id_buf) * (u32) CUR_CYLS(id_buf) * (u32) CUR_SECTORS(id_buf)) {
    585638    /* BIOS-supplied (aka "current") geometry values look valid */
    586639    geometry->NumHeads        = CUR_HEADS(id_buf);
     
    588641    geometry->TotalCylinders  = CUR_CYLS(id_buf);
    589642    Method = "BIOS";
    590   } else if (ATA_HEADS(id_buf) > 0 && ATA_CYLS(id_buf) > 0 &&
    591              ATA_SECTORS(id_buf) > 0) {
     643  } else if (ATA_HEADS(id_buf) > 0 && ATA_CYLS(id_buf) > 0 && ATA_SECTORS(id_buf) > 0) {
    592644    /* ATA-supplied values for geometry look valid */
    593645    geometry->NumHeads        = ATA_HEADS(id_buf);
     
    599651    geometry->NumHeads        = 255;
    600652    geometry->SectorsPerTrack = 63;
    601     geometry->TotalCylinders  = geometry->TotalSectors /
    602                                  ((u32) geometry->NumHeads *
    603                                   (u32) geometry->SectorsPerTrack);
     653    geometry->TotalCylinders  = geometry->TotalSectors / ((u32) geometry->NumHeads * (u32) geometry->SectorsPerTrack);
    604654    Method = "SCSI";
    605655  }
     656
     657  dprintf("Physical geometry: %ld cylinders, %d heads, %d sectors per track (%ldMB) (%s)\n",
     658      (u32) geometry->TotalCylinders, (u16) geometry->NumHeads, (u16) geometry->SectorsPerTrack,
     659      (u32) (geometry->TotalSectors / 2048), Method);
     660
     661  /* Fixup the geometry in case the geometry reported by the BIOS is bad */
     662  if (adjust_cylinders(geometry, geometry->TotalSectors)) { // cylinder overflow
     663    log_geom_calculate_LBA_assist(geometry, geometry->TotalSectors);
     664    geometry->TotalSectors = (USHORT)(geometry->NumHeads * geometry->SectorsPerTrack) * (ULONG)geometry->TotalCylinders;
     665  }
     666  adjust_cylinders(geometry, geometry->TotalSectors);
     667
     668  dprintf("Logical geometry: %ld cylinders, %d heads, %d sectors per track (%ldMB) (%s)\n",
     669      (u32) geometry->TotalCylinders, (u16) geometry->NumHeads, (u16) geometry->SectorsPerTrack,
     670      (u32) (geometry->TotalSectors / 2048), Method);
    606671
    607672  if (is_lvm_geometry(iorb)) Method = "LVM";
     
    612677  ad_infos[a].ports[p].devs[0].dev_info.Method = Method;
    613678
    614   dprintf("Drive geometry: %ld cylinders, %d heads, %d sectors per track (%ldMB) (%s)\n",
     679  dprintf("Reported geometry: %ld cylinders, %d heads, %d sectors per track (%ldMB) (%s)\n",
    615680      (u32) geometry->TotalCylinders, (u16) geometry->NumHeads, (u16) geometry->SectorsPerTrack,
    616681      (u32) (geometry->TotalSectors / 2048), Method);
Note: See TracChangeset for help on using the changeset viewer.