Index: trunk/src/os2ahci/Makefile
===================================================================
--- trunk/src/os2ahci/Makefile	(revision 153)
+++ trunk/src/os2ahci/Makefile	(revision 154)
@@ -30,5 +30,5 @@
 # Define default build version if not specified in environment
 BLD_MAJOR=1
-BLD_MINOR=26 # must be 2 digits
+BLD_MINOR=27 # must be 2 digits
 BLD_REV=0 # not used at this time
 
@@ -149,5 +149,5 @@
     @AddToFile $^@,$#define BLD_MONTH,DATEMONTH
     @AddToFile $^@,$#define BLD_DAY,DATEDAY
-	@AddToFile $^@,$#define BLDLEVEL,BLDLEVEL2,$(VENDOR),$(BLD_MAJOR).$(BLD_MINOR),AHCI Driver (c) Mensys BV 2013
+    @AddToFile $^@,$#define BLDLEVEL,BLDLEVEL2,$(VENDOR),$(BLD_MAJOR).$(BLD_MINOR),AHCI Driver (c) Mensys BV 2013,$(FIXPACK)
 
 .asm.obj: .autodepend
@@ -188,6 +188,6 @@
 
 os2ahci.sym: os2ahci.map
-	wat2map.cmd $[@ $^*.ma1
-	$(MAPSYM) $^*.ma1
-	@%erase $^*.ma1
+    wat2map.cmd $[@ $^*.ma1
+    $(MAPSYM) $^*.ma1
+    @%erase $^*.ma1
 
Index: trunk/src/os2ahci/README
===================================================================
--- trunk/src/os2ahci/README	(revision 153)
+++ trunk/src/os2ahci/README	(revision 154)
@@ -106,5 +106,5 @@
 Option                 Description
 ------------------------------------------------------------------------------
-/c:<addr>              Set debug COM port base address in hex (default = 3f8);
+/c:<addr>              Set debug COM port base address in hex (default = 0);
                        if used, this option should come before any /d options.
                        If <addr> is set to 0, the COM port is turned off and
@@ -113,5 +113,5 @@
                        command "type os2ahci$"; see the OS2AHCI project page
                        at http://svn.ecomstation.nl/ahci/wiki/AhciTrace
-                       for more info.
+                       for more info. COM0=3f8, COM1=2f8
 /d                     Debug output on COM port/trace buffer; multiple "/d"
                        options will increase verbosity:
Index: trunk/src/os2ahci/ahci.c
===================================================================
--- trunk/src/os2ahci/ahci.c	(revision 153)
+++ trunk/src/os2ahci/ahci.c	(revision 154)
@@ -144,4 +144,5 @@
   ddprintf("ahci_save_bios_config: BIOS AHCI mode is %d\n", ai->bios_config[HOST_CTL / sizeof(u32)] & HOST_AHCI_EN);
 
+#if 0
   if ((ai->bios_config[HOST_CTL / sizeof(u32)] & HOST_AHCI_EN) == 0 &&
       ai->pci->vendor == PCI_VENDOR_ID_INTEL) {
@@ -151,4 +152,5 @@
     init_reset = 1;
   }
+#endif
 
   /* HOST_CAP2 only exists for AHCI V1.2 and later */
@@ -676,8 +678,8 @@
     if (ai->port_map & (1UL << p)) {
       if (init_reset) {
-        dprintf("ahci_complete_init: resetting port %d\n", p);
+        ddprintf("ahci_complete_init: resetting port %d\n", p);
         ahci_reset_port(ai, p, 1);
       } else {
-        dprintf("ahci_complete_init: restarting port #%d\n", p);
+        ddprintf("ahci_complete_init: restarting port #%d\n", p);
         ahci_stop_port(ai, p);
         ahci_start_port(ai, p, 1);
@@ -718,5 +720,5 @@
   int timeout;
 
-  dprintf("ahci_reset_port: resetting port %d.%d\n", ad_no(ai), p);
+  ddprintf("ahci_reset_port: resetting port %d.%d\n", ad_no(ai), p);
   if (debug > 1) {
     printf(" PORT_CMD       = 0x%lx\n", readl(port_mmio + PORT_CMD));
@@ -749,12 +751,11 @@
   /* set link speed and power management options */
   ddprintf("ahci_reset_port: setting link speed and power management options\n");
-  tmp = readl(port_mmio + PORT_SCR_CTL) & ~0x00000fffUL; //DAZ
+  tmp = readl(port_mmio + PORT_SCR_CTL) & ~0x00000fffUL;
   tmp |= ((u32) link_speed[ad_no(ai)][p] & 0x0f) << 4;
   tmp |= ((u32) link_power[ad_no(ai)][p] & 0x0f) << 8;
-  //DAZ writel(port_mmio + PORT_SCR_CTL, tmp);
+  writel(port_mmio + PORT_SCR_CTL, tmp);
 
   /* issue COMRESET on the port */
   ddprintf("ahci_reset_port: issuing COMRESET on port %d\n", p);
-  //DAZ tmp = readl(port_mmio + PORT_SCR_CTL) & ~0x0000000fUL;
   writel(port_mmio + PORT_SCR_CTL, tmp | 1);
   readl(port_mmio + PORT_SCR_CTL);  /* flush */
@@ -810,21 +811,7 @@
   u8 _far *port_mmio = port_base(ai, p);
   u32 status;
-  //int timeout;
-
-  dprintf("ahci_start_port %d.%d\n", ad_no(ai), p);
+
+  ddprintf("ahci_start_port %d.%d\n", ad_no(ai), p);
   /* check whether device presence is detected and link established */
-
-#if 0
-  /* wait for communication to be re-established after port reset */
-  timeout = 5000;
-  while (((status = readl(port_mmio + PORT_SCR_STAT)) & 3) != 3) {
-    mdelay(10);
-    timeout -= 10;
-    if (timeout <= 0) {
-      dprintf("ahci_start_port #%d (PORT_SCR_STAT = 0x%lx)\n", p, status);
-      return(-1);
-    }
-  }
-#endif
 
   status = readl(port_mmio + PORT_SCR_STAT);
@@ -920,5 +907,5 @@
   int rc;
 
-  dprintf("ahci_stop_port %d.%d\n", ad_no(ai), p);
+  ddprintf("ahci_stop_port %d.%d\n", ad_no(ai), p);
 
   /* disable port interrupts */
@@ -1195,6 +1182,5 @@
 
   /* restart/reset port (includes the necessary port configuration) */
-  if ((ai->bios_config[HOST_CTL / sizeof(u32)] & HOST_AHCI_EN) == 0 &&
-      ai->pci->vendor == PCI_VENDOR_ID_INTEL) {
+  if (init_reset) {
     /* As outlined in ahci_restore_bios_config(), switching back and
      * forth between SATA and AHCI mode requires a COMRESET to force
@@ -1803,3 +1789,2 @@
 }
 
-
Index: trunk/src/os2ahci/ata.c
===================================================================
--- trunk/src/os2ahci/ata.c	(revision 153)
+++ trunk/src/os2ahci/ata.c	(revision 154)
@@ -442,4 +442,51 @@
 
 /******************************************************************************
+ * Try to read LVM information from the disk. If found, use the LVM geometry.
+ * This function will only work at init time. A better strategy would be to
+ * calculate the geometry during ahci_scan_ports and save it away and then just
+ * return the saved values when ata_get_geometry() is called.
+ */
+int is_lvm_geometry(IORBH _far *iorb)
+{
+  ADD_WORKSPACE _far *aws = add_workspace(iorb);
+  AD_INFO *ai = ad_infos + iorb_unit_adapter(iorb);
+  GEOMETRY _far *geometry = ((IORB_GEOMETRY _far *) iorb)->pGeometry;
+  PDLA_Table_Sector pDLA;
+  int p = iorb_unit_port(iorb);
+  int d = iorb_unit_device(iorb);
+  int rc;
+  ULONG sector;
+
+  if (init_complete) return 0; /* We cannot use ahci_exec_polled_cmd() after init_complete */
+
+  if (use_lvm_info) {
+    ddprintf("is_lvm_geometry (%d.%d.%d)\n", ad_no(ai), p, d);
+
+    for (sector = 255; sector >= 63; sector >>= 1) {
+      rc = ahci_exec_polled_cmd(ai, p, 0, 500, ATA_CMD_READ,
+             AP_SECTOR_28, (u32) sector-1,
+             AP_COUNT, (u16) 1,
+             AP_VADDR, (void _far *) aws->buf, 512,
+             AP_DEVICE, 0x40,
+             AP_END);
+      if (rc) continue;
+
+      pDLA = (PDLA_Table_Sector)aws->buf;
+      ddphex(pDLA, sizeof(DLA_Table_Sector), "DLA sector %d:\n", sector-1);
+
+      if ((pDLA->DLA_Signature1 == DLA_TABLE_SIGNATURE1) && (pDLA->DLA_Signature2 == DLA_TABLE_SIGNATURE2)) {
+        ddprintf("is_lvm_geometry found at sector %d\n", sector);
+        geometry->TotalCylinders = pDLA->Cylinders;
+        geometry->NumHeads = pDLA->Heads_Per_Cylinder;
+        geometry->SectorsPerTrack = pDLA->Sectors_Per_Track;
+        return 1;
+      }
+    }
+  }
+
+  return 0;
+}
+
+/******************************************************************************
  * Post processing function for ata_get_geometry(): convert the ATA identify
  * information to OS/2 IOCC_GEOMETRY information.
@@ -452,4 +499,5 @@
   int a = iorb_unit_adapter(iorb);
   int p = iorb_unit_port(iorb);
+  char *Method;
 
   /* Fill-in geometry information; the ATA-8 spec declares the geometry
@@ -500,4 +548,5 @@
   }
 
+  Method = "None";
   /* fabricate the remaining geometry fields */
   if (track_size[a][p] != 0) {
@@ -511,5 +560,5 @@
 				 ((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 &&
@@ -521,5 +570,5 @@
     geometry->SectorsPerTrack = CUR_SECTORS(id_buf);
     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) {
@@ -528,5 +577,5 @@
     geometry->SectorsPerTrack = ATA_SECTORS(id_buf);
     geometry->TotalCylinders  = ATA_CYLS(id_buf);
-
+    Method = "ATA";
   } else {
     /* use typical SCSI geometry */
@@ -536,12 +585,13 @@
 				 ((u32) geometry->NumHeads *
 				  (u32) geometry->SectorsPerTrack);
-  }
+    Method = "SCSI";
+  }
+
+  if (is_lvm_geometry(iorb)) Method = "LVM";
 
   if (debug) {
-    printf("geometry information:\n");
-    printf("  heads:     %d\n", (u16) geometry->NumHeads);
-    printf("  sectors:   %d\n", (u16) geometry->SectorsPerTrack);
-    printf("  cylinders: %d\n", (u16) geometry->TotalCylinders);
-    printf("  capacity:  %ldMB\n", (u32) (geometry->TotalSectors / 2048));
+    printf("Drive geometry: %d cylinders, %d heads, %d sectors per track (%ldMB) (%s)\n",
+        (u16) 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 153)
+++ trunk/src/os2ahci/libc.c	(revision 154)
@@ -62,5 +62,5 @@
 
 /* debug COM port base address */
-u16 com_base = 0x03f8;
+u16 com_base = 0;
 
 static char  hex_digits[] = "0123456789abcdef";
@@ -295,10 +295,10 @@
   len += vsprintf(buf + len, fmt, va);
 
-   if (com_base == 0) {
-     /* write debug message to trace buffer, not COM port */
-     trace_write(buf, len);
-     spin_unlock(com_lock);
-     return;
-   }
+  if (com_base == 0) {
+    /* write debug message to trace buffer, not COM port */
+    trace_write(buf, len);
+    spin_unlock(com_lock);
+    return;
+  }
 
   /* write debug message to serial port */
Index: trunk/src/os2ahci/os2ahci.c
===================================================================
--- trunk/src/os2ahci/os2ahci.c	(revision 153)
+++ trunk/src/os2ahci/os2ahci.c	(revision 154)
@@ -90,4 +90,5 @@
 int             verbosity = 1;     /* == 1 -> show sign on banner
                                     *  > 1 -> show adapter info during boot */
+int             use_lvm_info = 1;
 
 PFN             Device_Help = 0;   /* pointer to device helper entry point */
@@ -343,4 +344,8 @@
         break;
 
+      case 'z':
+        use_lvm_info = !invert_option;
+        break;
+
       case 'v':
         /* be verbose during boot */
@@ -377,8 +382,11 @@
   if (TRACE_ACTIVE) {
     /* debug is on, but COM port is off -> use our trace buffer */
-    trace_init();
-  }
-  dprintf("BldLevel: %s\n", BldLevel);
-  dprintf("CmdLine: %Fs\n", cmd_line);
+    trace_init(AHCI_TRACE_BUF_SIZE);
+  } else {
+    trace_init(AHCI_INFO_BUF_SIZE);
+  }
+
+  printf_nts("BldLevel: %s\n", BldLevel);
+  printf_nts("CmdLine: %Fs\n", cmd_line);
 
   /* scan PCI bus for supported devices */
@@ -390,6 +398,5 @@
     mdelay_cal();
 
-    if (DevHelp_RegisterDeviceClass(drv_name, (PFN) add_entry, 0, 1,
-                                    &add_handle)) {
+    if (DevHelp_RegisterDeviceClass(drv_name, (PFN) add_entry, 0, 1, &add_handle)) {
       cprintf("%s: couldn't register device class\n", drv_name);
       goto init_fail;
@@ -466,5 +473,7 @@
     case OS2AHCI_IDC_BIOSMODE:
       /* reconfigure adapters in BIOS/int13 mode; needed for generating
-       * trap dumps on some machines. This is called by ACPI.PSD.
+       * trap dumps on some machines. This was intended to be called by ACPI.PSD,
+       * but that is never done. This is obslete. The kernel exit accomplishes
+       * this instead.
        *
        * To enter BIOS mode, we flush all write caches, turn off interrupts
@@ -500,8 +509,5 @@
 USHORT char_dev_input(RP_RWV _far *rwrb)
 {
-  if (TRACE_ACTIVE) {
-    return(trace_char_dev(rwrb));
-  }
-  return(STDON | STATUS_ERR_UNKCMD);
+  return(trace_char_dev(rwrb));
 }
 
@@ -804,5 +810,5 @@
       init_complete = 1;
 
-      /* DAZ turn off COM port output */
+      /* DAZ turn off COM port output if on */
       com_base = 0;
 
@@ -814,4 +820,6 @@
       /* register APM hook */
       apm_init();
+
+      if (!TRACE_ACTIVE) build_user_info();
     }
     iorb_done(iorb);
@@ -1571,2 +1579,3 @@
   dprintf("Registered kernel exit routine for INT13 mode\n");
 }
+
Index: trunk/src/os2ahci/os2ahci.h
===================================================================
--- trunk/src/os2ahci/os2ahci.h	(revision 153)
+++ trunk/src/os2ahci/os2ahci.h	(revision 154)
@@ -119,4 +119,6 @@
 
 /* TRACE macros (for our internal ring buffer trace) */
+#define AHCI_TRACE_BUF_SIZE  0x8000U /* 32k */
+#define AHCI_INFO_BUF_SIZE  0x1000U /* 4k */
 #define TRACE_ACTIVE  (debug > 0 && com_base == 0)
 
@@ -386,4 +388,31 @@
   BUF_TO_SG                            /* copy from buffer to S/G list */
 } SG_MEMCPY_DIRECTION;
+
+/* Define the size of a disk name.  Disk Names are user defined names given to physical disk drives in the system. */
+#define DLA_TABLE_SIGNATURE1  0x424D5202L
+#define DLA_TABLE_SIGNATURE2  0x44464D50L
+#define DISK_NAME_SIZE	  20
+
+typedef struct _DLA_Table_Sector { /* DTS */
+     ULONG DLA_Signature1;         /* The magic signature (part 1) of a Drive Letter Assignment Table. */
+     ULONG DLA_Signature2;         /* The magic signature (part 2) of a Drive Letter Assignment Table. */
+     ULONG DLA_CRC;                /* The 32 bit CRC for this sector.  Calculated assuming that this field and all unused space in the sector is 0. */
+     ULONG Disk_Serial_Number;     /* The serial number assigned to this disk. */
+     ULONG Boot_Disk_Serial_Number;/* The serial number of the disk used to boot the system.  This is for conflict resolution when multiple volumes
+                                      want the same drive letter.  Since LVM.EXE will not let this situation happen, the only way to get this situation
+                                      is for the disk to have been altered by something other than LVM.EXE, or if a disk drive has been moved from one
+                                      machine to another.  If the drive has been moved, then it should have a different Boot_Disk_Serial_Number.  Thus,
+                                      we can tell which disk drive is the "foreign" drive and therefore reject its claim for the drive letter in question.
+                                      If we find that all of the claimaints have the same Boot_Disk_Serial_Number, then we must assign drive letters on
+                                      a first come, first serve basis.                                          */
+     ULONG Install_Flags;          /* Used by the Install program. */
+     ULONG Cylinders;
+     ULONG Heads_Per_Cylinder;
+     ULONG Sectors_Per_Track;
+     char  Disk_Name[DISK_NAME_SIZE];  /* The name assigned to the disk containing this sector. */
+     UCHAR Reboot;                 /* For use by Install.  Used to keep track of reboots initiated by install. */
+     BYTE  Reserved[3];            /* Alignment. */
+                                   /* These are the four entries which correspond to the entries in the partition table. */
+} DLA_Table_Sector, *PDLA_Table_Sector;
 
 /* -------------------------- function prototypes -------------------------- */
@@ -498,10 +527,10 @@
 
 /* trace.c */
-extern void        trace_init    (void);
+extern void        trace_init    (u16);
 extern void        trace_exit    (void);
 extern void        trace_write   (u8 _far *s, int len);
 extern u16         trace_read    (u8 _far *buf, u16 cb_buf);
-//NOT_USED extern u16         trace_bytes_avail(void);
 extern u16         trace_char_dev(RP_RWV _far *rwrb);
+extern void        build_user_info(void);
 
 /* pci.c */
@@ -544,4 +573,5 @@
 extern int           force_write_cache; /* if != 0, force write cache */
 extern int           verbosity;     /* if != 0, show some info during boot */
+extern int           use_lvm_info;
 
 extern HDRIVER       rm_drvh;       /* resource manager driver handle */
Index: trunk/src/os2ahci/trace.c
===================================================================
--- trunk/src/os2ahci/trace.c	(revision 153)
+++ trunk/src/os2ahci/trace.c	(revision 154)
@@ -28,6 +28,4 @@
 
 /* -------------------------- macros and constants ------------------------- */
-
-#define AHCI_TRACE_BUF_SIZE  0x8000U /* 32k */
 
 /* ------------------------ typedefs and structures ------------------------ */
@@ -53,24 +51,26 @@
  *       a GDT selector for the trace ring buffer
  */
-void trace_init(void)
+void trace_init(u16 usBufSize)
 {
   SEL sel = 0;
+
+  if (ahci_trace_buf.phys_addr) return;
 
   /* initialize ring buffer logic */
   ahci_trace_buf.writep = 0;
   ahci_trace_buf.readp = 0;
-  ahci_trace_buf.mask = AHCI_TRACE_BUF_SIZE - 1;
+  ahci_trace_buf.mask = usBufSize - 1;
 
   if (ahci_trace_buf.phys_addr == 0) {
     /* allocate buffer */
-    if (DevHelp_AllocPhys((ULONG) AHCI_TRACE_BUF_SIZE, MEMTYPE_ABOVE_1M,
+    if (DevHelp_AllocPhys((ULONG) usBufSize, MEMTYPE_ABOVE_1M,
                          &(ahci_trace_buf.phys_addr))) {
       /* failed above 1MB, try below */
-      if (DevHelp_AllocPhys((ULONG) AHCI_TRACE_BUF_SIZE, MEMTYPE_BELOW_1M,
+      if (DevHelp_AllocPhys((ULONG) usBufSize, MEMTYPE_BELOW_1M,
                             &(ahci_trace_buf.phys_addr))) {
         /* failed, too. Give up */
         ahci_trace_buf.phys_addr = 0;
         cprintf("%s warning: failed to allocate %dk trace buffer\n",
-                drv_name, AHCI_TRACE_BUF_SIZE / 1024);
+                drv_name, usBufSize / 1024);
         return;
       }
@@ -80,5 +80,5 @@
     if (DevHelp_AllocGDTSelector(&sel, 1) ||
         DevHelp_PhysToGDTSelector(ahci_trace_buf.phys_addr,
-                                  AHCI_TRACE_BUF_SIZE, sel)) {
+                                  usBufSize, sel)) {
       /* failed; free GDT selector and physical memory we allocated before */
       if (sel) {
@@ -95,6 +95,4 @@
 
   }
-
-
 }
 
@@ -182,27 +180,4 @@
   return cb_read;
 }
-
-#ifdef NOT_USED
-/******************************************************************************
- * return number of bytes we can read from the trace buffer
- */
-u16 trace_bytes_avail(void)
-{
-
-  if (ahci_trace_buf.writep == ahci_trace_buf.readp ) return 0; /* buffer is empty */
-
-  if (ahci_trace_buf.readp <= ahci_trace_buf.writep) {
-    /* read pointer is smaller than write pointer; no wrap in between */
-    if (ahci_trace_buf.writep == ahci_trace_buf.readp) {
-      /* full buffer available */
-      return AHCI_TRACE_BUF_SIZE;
-    }
-    return ahci_trace_buf.writep - ahci_trace_buf.readp;
-  }
-
-  /* read pointer is larger than write pointer; buffer wrapped */
-  return AHCI_TRACE_BUF_SIZE - ahci_trace_buf.readp + ahci_trace_buf.writep;
-}
-#endif
 
 /******************************************************************************
@@ -251,2 +226,32 @@
   return(STDON);
 }
+
+/******************************************************************************
+ * Create adapter/port/device list for user output.
+ */
+void build_user_info(void)
+{
+  int a;
+  int p;
+  int d;
+
+  for (a = 0; a < ad_info_cnt; a++) {
+    AD_INFO *ai = ad_infos + a;
+
+    printf_nts("Adapter %d: %d:%d:%d irq=%d addr=0x%lx\n", a,
+      ai->bus, ai->dev_func>>3, ai->dev_func&7,
+      ai->irq, ai->mmio_phys);
+
+    for (p = 0; p <= ai->port_max; p++) {
+      P_INFO *pi = &ai->ports[p];
+
+      printf_nts("  Port %d:\n", p);
+
+      for (d = 0; d <= pi->dev_max; d++) {
+        if (!pi->devs[d].present) continue;
+        printf_nts("    Drive %d: atapi=%d, removable=%d\n", d, pi->devs[d].atapi, pi->devs[d].removable);
+      }
+    }
+  }
+}
+
