Index: trunk/src/os2ahci/Makefile
===================================================================
--- trunk/src/os2ahci/Makefile	(revision 167)
+++ trunk/src/os2ahci/Makefile	(revision 169)
@@ -30,5 +30,5 @@
 # Define default build version if not specified in environment
 BLD_MAJOR=1
-BLD_MINOR=30 # must be 2 digits
+BLD_MINOR=31 # must be 2 digits
 BLD_REV=0 # not used at this time
 FIXPACK=
@@ -92,4 +92,7 @@
 CFLAGS= -ei -6 -d0 -bt=os2 -ms -zu -wx -ecc -zp1 -q -s -zgp -zfp -oi
 CFLAGS_DEBUG = -ei -6 -d3 -hc -bt=os2 -ms -zu -ecc -zp1 -q -s -zgp -zfp -od
+!ifneq FIXPACK
+CFLAGS+= -DTESTVER
+!endif
 
 ###############################################################################
Index: trunk/src/os2ahci/README
===================================================================
--- trunk/src/os2ahci/README	(revision 167)
+++ trunk/src/os2ahci/README	(revision 169)
@@ -394,4 +394,8 @@
 ==========
 
+v.1.31 04-Aug-2013 - David Azarewicz
+  Enhanced debug output.
+  Added code to check for bad geometries reported by the BIOS and fix them.
+
 v.1.30 29-Jun-2013 - David Azarewicz
   Enhanced debug log output
Index: trunk/src/os2ahci/ahci.c
===================================================================
--- trunk/src/os2ahci/ahci.c	(revision 167)
+++ trunk/src/os2ahci/ahci.c	(revision 169)
@@ -265,4 +265,5 @@
   }
   ai->flags = initial_flags[ai->pci->board];
+  ai->hw_ports = (ai->cap & 0x1f) + 1;
 
   if ((ai->cap & HOST_CAP_64) && (ai->flags & AHCI_HFLAG_32BIT_ONLY)) {
@@ -298,4 +299,5 @@
     dprintf("JMB361 has only one port, port_map 0x%lx -> 0x%lx\n", ai->port_map, 1);
     ai->port_map = 1;
+    ai->hw_ports = 1;
   }
 
@@ -309,5 +311,5 @@
    *       in ahci_scan_ports().
    */
-  ports = (ai->cap & 0x1f) + 1;
+  ports = ai->hw_ports;
   for (i = 0; i < AHCI_MAX_PORTS; i++) {
     if (ai->port_map & (1UL << i)) {
@@ -317,5 +319,5 @@
   if (ports < 0) {
     /* more ports in port_map than in HOST_CAP & 0x1f */
-    ports = (ai->cap & 0x1f) + 1;
+    ports = ai->hw_ports;
     dprintf("implemented port map (0x%lx) contains more "
             "ports than nr_ports (%d), using nr_ports\n",
Index: trunk/src/os2ahci/ata.c
===================================================================
--- trunk/src/os2ahci/ata.c	(revision 167)
+++ trunk/src/os2ahci/ata.c	(revision 169)
@@ -440,4 +440,62 @@
 
   return(rc);
+}
+
+/* Adjust the cylinder count in the physical
+ * geometry to the last full cylinder.
+ */
+int adjust_cylinders(GEOMETRY _far *geometry, ULONG TotalSectors) {
+  USHORT SecPerCyl;
+  int rc = FALSE;
+
+  geometry->TotalSectors = TotalSectors;
+  SecPerCyl = geometry->SectorsPerTrack * geometry->NumHeads;
+  if (SecPerCyl > 0) {
+    ULONG TotalCylinders  = TotalSectors / SecPerCyl;
+
+    geometry->TotalSectors   = TotalCylinders * SecPerCyl;
+    geometry->TotalCylinders = TotalCylinders;
+    if (TotalCylinders >> 16) {
+      geometry->TotalCylinders = 65535;
+      rc = TRUE;
+    }
+  }
+  return (rc);
+}
+
+/* Calculate the logical geometry based on the input physcial geometry
+ * using the LBA Assist Translation algorithm.
+ */
+#define BIOS_MAX_CYLINDERS       1024l
+#define BIOS_MAX_NUMHEADS         255
+#define BIOS_MAX_SECTORSPERTRACK   63
+void log_geom_calculate_LBA_assist(GEOMETRY _far *geometry, ULONG TotalSectors)
+{
+  UCHAR numSpT   = BIOS_MAX_SECTORSPERTRACK;
+  UCHAR numHeads = BIOS_MAX_NUMHEADS;
+  ULONG Cylinders;
+
+  if (TotalSectors <= (BIOS_MAX_CYLINDERS * 128 * BIOS_MAX_SECTORSPERTRACK)) {
+    USHORT temp = (TotalSectors - 1) / (BIOS_MAX_CYLINDERS * BIOS_MAX_SECTORSPERTRACK);
+
+    if (temp < 16)      numHeads = 16;
+    else if (temp < 32) numHeads = 32;
+    else if (temp < 64) numHeads = 64;
+    else                numHeads = 128;
+  }
+
+  do {
+    Cylinders = TotalSectors / (USHORT)(numHeads * numSpT);
+    if (Cylinders >> 16) {
+      if (numSpT < 128)
+        numSpT = (numSpT << 1) | 1;
+      else
+        Cylinders = 65535; // overflow !
+    }
+  } while (Cylinders >> 16);
+
+  geometry->TotalCylinders  = Cylinders;
+  geometry->NumHeads        = numHeads;
+  geometry->SectorsPerTrack = numSpT;
 }
 
@@ -574,13 +632,8 @@
     geometry->NumHeads        = 255;
     geometry->SectorsPerTrack = track_size[a][p];
-    geometry->TotalCylinders  = geometry->TotalSectors /
-				 ((u32) geometry->NumHeads *
-				  (u32) geometry->SectorsPerTrack);
+    geometry->TotalCylinders  = geometry->TotalSectors / ((u32) geometry->NumHeads * (u32) geometry->SectorsPerTrack);
     Method = "Custom";
-  } else if (CUR_HEADS(id_buf) > 0 && CUR_CYLS(id_buf) > 0 &&
-             CUR_SECTORS(id_buf) > 0 &&
-             CUR_CAPACITY(id_buf) == (u32) CUR_HEADS(id_buf) *
-                                     (u32) CUR_CYLS(id_buf) *
-                                     (u32) CUR_SECTORS(id_buf)) {
+  } else if (CUR_HEADS(id_buf) > 0 && CUR_CYLS(id_buf) > 0 && CUR_SECTORS(id_buf) > 0 &&
+             CUR_CAPACITY(id_buf) == (u32) CUR_HEADS(id_buf) * (u32) CUR_CYLS(id_buf) * (u32) CUR_SECTORS(id_buf)) {
     /* BIOS-supplied (aka "current") geometry values look valid */
     geometry->NumHeads        = CUR_HEADS(id_buf);
@@ -588,6 +641,5 @@
     geometry->TotalCylinders  = CUR_CYLS(id_buf);
     Method = "BIOS";
-  } else if (ATA_HEADS(id_buf) > 0 && ATA_CYLS(id_buf) > 0 &&
-             ATA_SECTORS(id_buf) > 0) {
+  } else if (ATA_HEADS(id_buf) > 0 && ATA_CYLS(id_buf) > 0 && ATA_SECTORS(id_buf) > 0) {
     /* ATA-supplied values for geometry look valid */
     geometry->NumHeads        = ATA_HEADS(id_buf);
@@ -599,9 +651,22 @@
     geometry->NumHeads        = 255;
     geometry->SectorsPerTrack = 63;
-    geometry->TotalCylinders  = geometry->TotalSectors /
-				 ((u32) geometry->NumHeads *
-				  (u32) geometry->SectorsPerTrack);
+    geometry->TotalCylinders  = geometry->TotalSectors / ((u32) geometry->NumHeads * (u32) geometry->SectorsPerTrack);
     Method = "SCSI";
   }
+
+  dprintf("Physical geometry: %ld cylinders, %d heads, %d sectors per track (%ldMB) (%s)\n",
+      (u32) geometry->TotalCylinders, (u16) geometry->NumHeads, (u16) geometry->SectorsPerTrack,
+      (u32) (geometry->TotalSectors / 2048), Method);
+
+  /* Fixup the geometry in case the geometry reported by the BIOS is bad */
+  if (adjust_cylinders(geometry, geometry->TotalSectors)) { // cylinder overflow
+    log_geom_calculate_LBA_assist(geometry, geometry->TotalSectors);
+    geometry->TotalSectors = (USHORT)(geometry->NumHeads * geometry->SectorsPerTrack) * (ULONG)geometry->TotalCylinders;
+  }
+  adjust_cylinders(geometry, geometry->TotalSectors);
+
+  dprintf("Logical geometry: %ld cylinders, %d heads, %d sectors per track (%ldMB) (%s)\n",
+      (u32) geometry->TotalCylinders, (u16) geometry->NumHeads, (u16) geometry->SectorsPerTrack,
+      (u32) (geometry->TotalSectors / 2048), Method);
 
   if (is_lvm_geometry(iorb)) Method = "LVM";
@@ -612,5 +677,5 @@
   ad_infos[a].ports[p].devs[0].dev_info.Method = Method;
 
-  dprintf("Drive geometry: %ld cylinders, %d heads, %d sectors per track (%ldMB) (%s)\n",
+  dprintf("Reported geometry: %ld cylinders, %d heads, %d sectors per track (%ldMB) (%s)\n",
       (u32) geometry->TotalCylinders, (u16) geometry->NumHeads, (u16) geometry->SectorsPerTrack,
       (u32) (geometry->TotalSectors / 2048), Method);
Index: trunk/src/os2ahci/libc.c
===================================================================
--- trunk/src/os2ahci/libc.c	(revision 167)
+++ trunk/src/os2ahci/libc.c	(revision 169)
@@ -215,12 +215,10 @@
 
       case 'd':
-        long_to_asc((lmod) ? va_arg(va, long)
-                           : va_arg(va, int), buf, 10, zero, flen);
+        long_to_asc((lmod) ? va_arg(va, long) : va_arg(va, int), buf, 10, zero, flen);
         buf += strlen(buf);
         break;
 
       case 'x':
-        long_to_asc((lmod) ? va_arg(va, u32)
-                           : va_arg(va, u16), buf, 16, zero, flen);
+        long_to_asc((lmod) ? va_arg(va, u32) : va_arg(va, u16), buf, 16, zero, flen);
         buf += strlen(buf);
         break;
Index: trunk/src/os2ahci/os2ahci.c
===================================================================
--- trunk/src/os2ahci/os2ahci.c	(revision 167)
+++ trunk/src/os2ahci/os2ahci.c	(revision 169)
@@ -418,4 +418,8 @@
   ciprintf(init_msg, drv_name, VERSION / 100, VERSION % 100);
 
+  #ifdef TESTVER
+  #include "testver.c"
+  #endif
+
   /* scan PCI bus for supported devices */
   scan_pci_bus();
@@ -424,5 +428,4 @@
     /* initialization succeeded and we found at least one AHCI adapter */
     ADD_InitTimer(timer_pool, sizeof(timer_pool));
-    //NOT_USED mdelay_cal();
 
     if (DevHelp_RegisterDeviceClass(drv_name, (PFN) add_entry, 0, 1, &add_handle)) {
Index: trunk/src/os2ahci/os2ahci.h
===================================================================
--- trunk/src/os2ahci/os2ahci.h	(revision 167)
+++ trunk/src/os2ahci/os2ahci.h	(revision 169)
@@ -373,4 +373,6 @@
   unsigned      port_scan_done : 1;    /* if != 0, port scan already done */
   unsigned      busy : 1;              /* if != 0, adapter is busy */
+
+  unsigned      hw_ports : 6;          /* number of ports as reported by the hardware */
 
   u32           port_map;              /* bitmap of active ports */
@@ -558,6 +560,4 @@
 extern void        free          (void *ptr);
 extern ULONG       virt_to_phys  (void _far *ptr);
-//NOT_USED extern void        mdelay_cal    (void);
-//NOT_USED extern void        mdelay        (u32 millies);
 extern void        msleep        (u32 millies);
 extern void        panic         (char *msg);
@@ -625,4 +625,5 @@
 extern ULONG         drv_lock;      /* driver-level spinlock */
 extern ULONG         com_lock;      /* debug log spinlock */
+extern volatile PGINFOSEG gis;
 extern IORB_QUEUE    driver_queue;  /* driver-level IORB queue */
 extern AD_INFO       ad_infos[];    /* adapter information list */
Index: trunk/src/os2ahci/trace.c
===================================================================
--- trunk/src/os2ahci/trace.c	(revision 167)
+++ trunk/src/os2ahci/trace.c	(revision 169)
@@ -226,5 +226,5 @@
       ai->bios_config[HOST_VERSION / sizeof(u32)]);
 
-    for (p = 0; p <= ai->port_max; p++) {
+    for (p = 0; p < ai->hw_ports; p++) {
       P_INFO *pi = &ai->ports[p];
 
@@ -232,17 +232,20 @@
 
       for (d = 0; d <= pi->dev_max; d++) {
-        if (!pi->devs[d].present) continue;
-
-        ntprintf("    Drive %d:", d);
-        if (pi->devs[d].atapi) ntprintf(" atapi");
-        if (pi->devs[d].removable) ntprintf(" removable");
-        if (pi->devs[d].dev_info.Method != NULL)
-          ntprintf(" %d cylinders, %d heads, %d sectors per track (%ldMB) (%s)",
-            pi->devs[d].dev_info.Cylinders, pi->devs[d].dev_info.HeadsPerCylinder, pi->devs[d].dev_info.SectorsPerTrack,
-            pi->devs[d].dev_info.TotalSectors/2048, pi->devs[d].dev_info.Method);
-        ntprintf("\n");
-      }
-    }
-  }
-}
-
+        if (!pi->devs[d].present) {
+          ntprintf("    No drive present\n");
+        } else {
+          ntprintf("    Drive %d:", d);
+          if (pi->devs[d].atapi) ntprintf(" atapi");
+          if (pi->devs[d].removable) ntprintf(" removable");
+          if (pi->devs[d].dev_info.Method != NULL) {
+            ntprintf(" %ld cylinders, %d heads, %d sectors per track (%ldMB) (%s)",
+              (u32)pi->devs[d].dev_info.Cylinders, pi->devs[d].dev_info.HeadsPerCylinder, pi->devs[d].dev_info.SectorsPerTrack,
+              pi->devs[d].dev_info.TotalSectors/2048, pi->devs[d].dev_info.Method);
+          } else ntprintf(" Drive present but no information available. Not queried by OS.");
+          ntprintf("\n");
+        } /* if */
+      } /* for d */
+    } /* for p */
+  } /* for a */
+}
+
