Index: /trunk/src/os2ahci/ahci.c
===================================================================
--- /trunk/src/os2ahci/ahci.c	(revision 52)
+++ /trunk/src/os2ahci/ahci.c	(revision 53)
@@ -32,4 +32,8 @@
                               ? atapi_##func : ata_##func
 
+#define LBATEST_SECTORS_PER_READ     64
+#define LBATEST_SECTOR_SIZE         512
+
+#define LBATEST
 
 /* ------------------------ typedefs and structures ------------------------ */
@@ -39,4 +43,8 @@
 static void ahci_setup_device     (AD_INFO *ai, int p, int d, u16 *id_buf);
 static void _cdecl _far timeout_callback (ULONG timer_handle, ULONG p1, ULONG p2);
+
+#ifdef LBATEST
+static void lba_test              (AD_INFO *ai, int p, int d, u16 *id_buf);
+#endif
 
 /* ------------------------ global/static variables ------------------------ */
@@ -470,5 +478,4 @@
         ddphex(id_buf, 512, "ATA_IDENTIFY(_PACKET) results:\n");
         ahci_setup_device(ai, p, 0, id_buf);
-
       } else {
         /* no device attached to this port */
@@ -1506,4 +1513,17 @@
     pci_hack_virtualbox();
   }
+
+#ifdef LBATEST
+  /* if LBATEST is defined, we perform a sector mapping test
+   * for the first HD attached to the first adapter.
+   * The purose of this test is to determine if the sector
+   * mapping is correct throughout the entire disk.
+   */
+  if (total_dev_cnt == 1) {
+    lba_test(ai, p, 0, id_buf);
+  }
+#endif
+
+
 }
 
@@ -1550,2 +1570,88 @@
 }
 
+
+/*******************************************************************************
+ * Perform LBA to CHS mapping test.
+ * The purpose of this test is to find out if the driver's CHS to LBA mapping
+ * is correct throughout the entire physical hard disk.
+ *
+ * To perform the test, attach the test HD to a Linux box and run lbatest
+ * to write each sector's LBA to its first 4 bytes, then compile/install
+ * the driver with LBATEST defined.
+ */
+#ifdef LBATEST
+static void lba_test(AD_INFO *ai, int p, int d, u16 *id_buf)
+{
+  u32 total_sectors = 0;
+  u32 sector;
+  int i;
+  unsigned char _far *buf;
+  u32 err_cnt = 0;
+  int rc;
+  u16 cbt = LBATEST_SECTOR_SIZE * LBATEST_SECTORS_PER_READ;
+  u32 phys_addr;
+
+  /* determine number of sectors of this HD */
+  if (id_buf[ATA_ID_CFS_ENABLE_2] & 0x400) {
+    /* 48-bit LBA supported */
+    if (ATA_CAPACITY48_H(id_buf) != 0) {
+      /* more than 32 bits for number of sectors */
+      total_sectors = 0xffffffffUL;
+    } else {
+      total_sectors = ATA_CAPACITY48_L(id_buf);
+    }
+  } else {
+    /* 28-bit LBA */
+    total_sectors = ATA_CAPACITY(id_buf) & 0x0fffffffUL;
+  }
+
+  /* allocate buffer */
+  spin_lock(drv_lock);
+  if (DevHelp_AllocPhys(cbt, 1, &phys_addr)) {
+    printf("Failed to allocate %ld bytes phys memory for lbatest\n");
+    spin_unlock(drv_lock);
+    return;
+  }
+  if (DevHelp_PhysToVirt(phys_addr, (USHORT) cbt, (PVOID) &buf, &i)) {
+    printf("Failed to convert phys addr to virt\n");
+    DevHelp_FreePhys(phys_addr);
+    spin_unlock(drv_lock);
+    return;
+  }
+  spin_unlock(drv_lock);
+
+  /* go... */
+  memset(buf, 0x00, sizeof(buf));
+  for (sector = 0; sector < total_sectors; sector += LBATEST_SECTORS_PER_READ) {
+
+    /* write progress to serial terminal */
+    if (sector % 1000 == 0) {
+      printf("lbatest: read %ldk sectors\n", sector / 1000);
+    }
+
+    /* read appropriate number of sectors */
+    rc = ahci_exec_polled_cmd(ai, p, 0, 500, ATA_CMD_READ_EXT,
+                              AP_SECTOR_48, sector, (u16) 0,
+                              AP_VADDR, (void _far *) buf, cbt,
+                              AP_COUNT, (u16) LBATEST_SECTORS_PER_READ,
+                              AP_DEVICE, 0x4000,
+                              AP_END);
+
+    /* verify lba numbers */
+    for (i = 0; i < LBATEST_SECTORS_PER_READ; i++) {
+      if (*((u32 _far*)(buf + i * LBATEST_SECTOR_SIZE)) != sector + i) {
+        printf("lbatest: read LBA 0x%08lx from sector 0x%08lx\n",
+               *((u32 _far*) buf), sector + i);
+        err_cnt++;
+      }
+               
+    }
+  }
+
+  printf("lbatest: passed with %ld errors\n", err_cnt);
+    
+cleanup_lbatest:
+  DevHelp_FreePhys(phys_addr);
+
+}
+#endif
