Index: /trunk/src/os2ahci/Makefile
===================================================================
--- /trunk/src/os2ahci/Makefile	(revision 192)
+++ /trunk/src/os2ahci/Makefile	(revision 193)
@@ -12,5 +12,5 @@
 # Define default build version if not specified in environment
 BLD_MAJOR=2
-BLD_MINOR=03 # must be 2 digits
+BLD_MINOR=04 # must be 2 digits
 BLD_REV=0 # not used at this time
 
@@ -166,7 +166,4 @@
   copy /b $(ROOT)\src\os2ahci\$(O)\os2ahci.sym $(ZIPDIR)\pkg1 >NUL
 
-  @md $(ZIPDIR)\pkg2
-  @copy /b $(ROOT)\Tools\smartahci.exe $(ZIPDIR)\pkg2 >NUL
-
   @md $(ZIPDIR)\pkg20
   @copy $(ROOT)\src\os2ahci\ReadMe.txt $(ZIPDIR)\pkg20 >NUL
Index: /trunk/src/os2ahci/ReadMe.txt
===================================================================
--- /trunk/src/os2ahci/ReadMe.txt	(revision 192)
+++ /trunk/src/os2ahci/ReadMe.txt	(revision 193)
@@ -1,3 +1,3 @@
-AHCI Driver for OS/2 v2.03
+AHCI Driver for OS/2 v2.04
 
 Introduction
@@ -321,17 +321,7 @@
 
 Starting with version 1.22, OS2AHCI supports the IOCTL interface required by
-existing SMART monitoring tools. Since those tools are hard-coded to open
-the character device named "IBMS506$", they will not work with OS2AHCI unless
-modified to open the OS2AHCI$ device. Previous versions of OS2AHCI used to
-register a duplicate device with the IBMS506$ name, however since that caused
-so many unacceptable problems, that is no longer done. You must have a SMART
-utility that opens the OS2AHCI$ device to access the AHCI driver.
-
-A patched version of the smartctl.exe program is included in the OS2AHCI
-distribution. This patched version simply has the name "IBMS506$" changed
-to "OS2AHCI$" and is otherwise identical. This patched program has been
-renamed to smartahci.exe to distinguish it from the unpatched version.
-The patched smartahci.exe program is provided AS-IS and is completely
-UNSUPPORTED. Use of this program is at your own risk.
+existing SMART monitoring tools. Beware that the IBM version of smartctl.exe
+is hard-coded to open the character device named "IBMS506$" so it will not
+work with OS2AHCI. You must use a version that allows specifying ahci devices.
 
 NOTES:
@@ -360,4 +350,5 @@
 
 Hot swap is not supported.
+Port expanders are not supported. Only one drive per port is allowed.
 
 
@@ -387,4 +378,9 @@
 Change Log
 ==========
+
+v.2.04 06-Dec-2017 - David Azarewicz
+  Cosmetic changes to user display.
+  Fixed the ioctl pass-thru interface.
+  Removed the old IBM smartctl.exe from the distribution.
 
 v.2.03 15-Jul-2017 - David Azarewicz
Index: /trunk/src/os2ahci/ahci.c
===================================================================
--- /trunk/src/os2ahci/ahci.c	(revision 192)
+++ /trunk/src/os2ahci/ahci.c	(revision 193)
@@ -504,4 +504,12 @@
   }
 
+  if (ai->pci_vendor == PCI_VENDOR_ID_INTEL)
+  {
+    /* Adapter is not in AHCI mode and the spec says a COMRESET is
+     * required when switching from SATA to AHCI mode and vice versa.
+     */
+    init_reset = 1;
+  }
+
   /* some controllers need AHCI_EN to be written multiple times */
   for (i = 0; i < 5; i++)
Index: /trunk/src/os2ahci/ioctl.c
===================================================================
--- /trunk/src/os2ahci/ioctl.c	(revision 192)
+++ /trunk/src/os2ahci/ioctl.c	(revision 193)
@@ -55,13 +55,11 @@
   SCATGATENTRY        sg_lst[AHCI_MAX_SG / 2]; /* scatter/gather list */
   ULONG               sg_cnt;                  /* number of S/G elements */
-  struct _KernVMLock_t *lh;                  /* lock handle for VMLock() */
+  struct _KernVMLock_t lh;                     /* lock handle for KernVMLock() */
 } IOCTL_CONTEXT;
 
 /* -------------------------- function prototypes -------------------------- */
 
-static USHORT do_smart  (BYTE unit, BYTE sub_func, BYTE cnt, BYTE lba_l,
-                         void *buf);
-static int    map_unit  (BYTE unit, USHORT *a, USHORT *p,
-                         USHORT *d);
+static USHORT do_smart(BYTE unit, BYTE sub_func, BYTE cnt, BYTE lba_l, void *buf);
+static int map_unit(BYTE unit, USHORT *a, USHORT *p, USHORT *d);
 
 extern IORBH FAR16DATA * (__far16 *Far16AdrOfIoctlWakeup16)(IORBH FAR16DATA*);
@@ -168,4 +166,16 @@
   memset(ic, 0x00, sizeof(*ic));
 
+  /* lock DMA transfer buffer into memory and construct S/G list */
+  if (req->buflen > 0)
+  {
+    if (KernVMLock(VMDHL_LONG | !((req->flags & PT_WRITE) ? VMDHL_WRITE : 0),
+                       req->buf, req->buflen, &ic->lh, (KernPageList_t*)&ic->sg_lst, &ic->sg_cnt) != 0)
+    {
+      /* couldn't lock buffer and/or produce a S/G list */
+      MemFree(ic);
+      return(RPDONE | RPERR_PARAMETER);
+    }
+  }
+
   /* fill in adapter passthrough fields */
   ic->iorb.iorbh.Length           = sizeof(ic->iorb);
@@ -200,10 +210,11 @@
 
   /* Wait for IORB completion. */
-  spin_lock(drv_lock);
+
+  //DAZ 20171206 spin_lock(drv_lock);
   while (!(ic->iorb.iorbh.Status & IORB_DONE))
   {
-    KernBlock((ULONG)&ic->iorb.iorbh, 30000, 0, NULL, NULL);
-  }
-  spin_unlock(drv_lock);
+    KernBlock(CastFar16ToULONG(MemFar16Adr(&ic->iorb.iorbh)), 30000, 0, NULL, NULL);
+  }
+  //DAZ 20171206 spin_unlock(drv_lock);
 
   ret = RPDONE;
@@ -270,5 +281,4 @@
       memcpy(sense_buf, ic->sense, min(ic->ssb.ReqSenseLen, req->sense_len));
     }
-
   }
   else if ((req->flags & PT_ATAPI) == 0)
@@ -282,4 +292,5 @@
 
   MemFree(ic);
+  if (req->buflen > 0) KernVMUnlock(&ic->lh);
   return(ret);
 }
@@ -393,29 +404,15 @@
 {
   DSKSP_CommandParameters *cp = (DSKSP_CommandParameters *)Far16ToFlat(ioctl->ioctl.pvParm);
-  USHORT size = 0;
   USHORT ret;
   UCHAR unit;
-  UCHAR parm;
+  UCHAR parm = 0;
+  void *pData = NULL;
 
   unit = cp->byPhysicalUnit;
 
-  /* verify addressability of data buffer (depends on SMART function) */
-  switch (ioctl->ioctl.bFunction)
-  {
-
-  case DSKSP_SMART_GETSTATUS:
-    size = sizeof(ULONG);
-    break;
-
-  case DSKSP_SMART_GET_ATTRIBUTES:
-  case DSKSP_SMART_GET_THRESHOLDS:
-  case DSKSP_SMART_GET_LOG:
-    size = 512;
-    break;
-  }
-
-  if (size > 0)
-  {
-    parm = *(UCHAR*)Far16ToFlat(ioctl->ioctl.pvData);
+  if (ioctl->ioctl.pvData)
+  {
+    pData = (void*)Far16ToFlat(ioctl->ioctl.pvData);
+    parm = *(UCHAR*)pData;
   }
 
@@ -444,17 +441,17 @@
 
   case DSKSP_SMART_GETSTATUS:
-    ret = do_smart(unit, ATA_SMART_STATUS, 0, 0, Far16ToFlat(ioctl->ioctl.pvData));
+    ret = do_smart(unit, ATA_SMART_STATUS, 0, 0, pData);
     break;
 
   case DSKSP_SMART_GET_ATTRIBUTES:
-    ret = do_smart(unit, ATA_SMART_READ_VALUES, 0, 0, Far16ToFlat(ioctl->ioctl.pvData));
+    ret = do_smart(unit, ATA_SMART_READ_VALUES, 0, 0, pData);
     break;
 
   case DSKSP_SMART_GET_THRESHOLDS:
-    ret = do_smart(unit, ATA_SMART_READ_THRESHOLDS, 0, 0, Far16ToFlat(ioctl->ioctl.pvData));
+    ret = do_smart(unit, ATA_SMART_READ_THRESHOLDS, 0, 0, pData);
     break;
 
   case DSKSP_SMART_GET_LOG:
-    ret = do_smart(unit, ATA_SMART_READ_LOG, 1, parm, Far16ToFlat(ioctl->ioctl.pvData));
+    ret = do_smart(unit, ATA_SMART_READ_LOG, 1, parm, pData);
     break;
 
Index: /trunk/src/os2ahci/trace.c
===================================================================
--- /trunk/src/os2ahci/trace.c	(revision 192)
+++ /trunk/src/os2ahci/trace.c	(revision 193)
@@ -25,4 +25,5 @@
   int p;
   int d;
+  int iFlag;
 
   for (a = 0; a < ad_info_cnt; a++)
@@ -37,16 +38,15 @@
       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];
-
-      dprintf(0,"  Port %d:\n", p);
+      iFlag = 1;
 
       for (d = 0; d <= pi->dev_max; d++)
       {
-        if (!pi->devs[d].present)
+        if (pi->devs[d].present)
         {
-          dprintf(0,"    No drive present\n");
-        } else {
+          if (iFlag) dprintf(0,"  Port %d:\n", p);
+          iFlag = 0;
           dprintf(0,"    Drive %d:", d);
           if (pi->devs[d].atapi) dprintf(0," atapi");
@@ -60,4 +60,10 @@
           dprintf(0,"\n");
           dprintf(0,"             Model: %s\n", pi->devs[d].dev_name);
+        }
+        else if (verbosity > 0)
+        {
+          if (iFlag) dprintf(0,"  Port %d:\n", p);
+          iFlag = 0;
+          dprintf(0,"    No drive present\n");
         } /* if */
       } /* for d */
