atapi, buslogic, cdrom, class2.
[reactos.git] / reactos / drivers / storage / atapi / atapi.c
index a836263..a004aa0 100644 (file)
 
 //  -------------------------------------------------------------------------
 
-#include <ddk/ntddk.h>
-#include <ddk/srb.h>
-#include <ddk/scsi.h>
-#include <ddk/ntddscsi.h>
-#include <ntos/kefuncs.h>
+#include <ntddk.h>
+#include <srb.h>
+#include <scsi.h>
+#include <ntddscsi.h>
+#include <ntdddisk.h>
+#include <ntddstor.h>
 
 #include "atapi.h"
 
 #define VERSION  "0.0.1"
 
 
+NTSTATUS NTAPI
+DriverEntry(IN PDRIVER_OBJECT DriverObject,
+            IN PUNICODE_STRING RegistryPath);
+
 //  -------------------------------------------------------  File Static Data
 
 #ifdef ENABLE_DMA
@@ -97,9 +102,9 @@ typedef struct _ATAPI_MINIPORT_EXTENSION
   PUCHAR DataBuffer;
   ULONG DataTransferLength;
 
-  BOOLEAN FASTCALL (*Handler)(IN struct _ATAPI_MINIPORT_EXTENSION* DevExt);
+  BOOLEAN (FASTCALL *Handler)(IN struct _ATAPI_MINIPORT_EXTENSION* DevExt);
 #ifdef ENABLE_DMA
-  BOOL UseDma;
+  BOOLEAN UseDma;
   ULONG PRDCount;
   ULONG PRDMaxCount;
   PPRD PRDTable;
@@ -167,7 +172,7 @@ PCI_NATIVE_CONTROLLER const PciNativeController[] =
 static BOOLEAN
 AtapiInitDma(PATAPI_MINIPORT_EXTENSION DevExt,
             PSCSI_REQUEST_BLOCK Srb,
-            BYTE cmd);
+            UCHAR cmd);
 #endif
 
 static ULONG STDCALL
@@ -207,8 +212,8 @@ AtapiStartIo(IN PVOID DeviceExtension,
 
 static VOID
 AtapiExecuteCommand(PATAPI_MINIPORT_EXTENSION DevExt,
-                   BYTE command,
-                   BOOLEAN FASTCALL (*Handler)(PATAPI_MINIPORT_EXTENSION));
+                   UCHAR command,
+                   BOOLEAN (FASTCALL *Handler)(PATAPI_MINIPORT_EXTENSION));
 
 static BOOLEAN STDCALL
 AtapiInterrupt(IN PVOID DeviceExtension);
@@ -219,6 +224,9 @@ AtapiNoDataInterrupt(PATAPI_MINIPORT_EXTENSION DevExt);
 static BOOLEAN FASTCALL
 AtapiPacketInterrupt(IN PATAPI_MINIPORT_EXTENSION DevExt);
 
+static BOOLEAN FASTCALL
+AtapiSmartInterrupt(IN PATAPI_MINIPORT_EXTENSION DevExt);
+
 static BOOLEAN FASTCALL
 AtapiReadInterrupt(IN PATAPI_MINIPORT_EXTENSION DevExt);
 
@@ -264,6 +272,10 @@ static ULONG
 AtapiSendIdeCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
                    IN PSCSI_REQUEST_BLOCK Srb);
 
+static ULONG
+AtapiSendSmartCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
+                      IN PSCSI_REQUEST_BLOCK Srb);
+
 static ULONG
 AtapiInquiry(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
             IN PSCSI_REQUEST_BLOCK Srb);
@@ -294,10 +306,10 @@ AtapiScsiSrbToAtapi (PSCSI_REQUEST_BLOCK Srb);
 //  ----------------------------------------------------------------  Inlines
 
 void
-IDESwapBytePairs(char *Buf,
+IDESwapBytePairs(UCHAR *Buf,
                  int Cnt)
 {
-  char  t;
+  UCHAR  t;
   int   i;
 
   for (i = 0; i < Cnt; i += 2)
@@ -330,7 +342,7 @@ IDESwapBytePairs(char *Buf,
 //  RETURNS:
 //    NTSTATUS
 
-STDCALL NTSTATUS
+NTSTATUS NTAPI
 DriverEntry(IN PDRIVER_OBJECT DriverObject,
             IN PUNICODE_STRING RegistryPath)
 {
@@ -450,9 +462,9 @@ AtapiClaimHwResources(PATAPI_MINIPORT_EXTENSION DevExt,
    }
    DevExt->Handler = NULL;
    DevExt->CommandPortBase = (ULONG)IoBase;
-   ConfigInfo->AccessRanges[0].RangeStart = IoAddress;
-   ConfigInfo->AccessRanges[0].RangeLength = 8;
-   ConfigInfo->AccessRanges[0].RangeInMemory = FALSE;
+   (*ConfigInfo->AccessRanges)[0].RangeStart = IoAddress;
+   (*ConfigInfo->AccessRanges)[0].RangeLength = 8;
+   (*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE;
 
    if (ControlPortBase)
    {
@@ -470,9 +482,9 @@ AtapiClaimHwResources(PATAPI_MINIPORT_EXTENSION DevExt,
          return FALSE;
       }
       DevExt->ControlPortBase = (ULONG)IoBase;
-      ConfigInfo->AccessRanges[1].RangeStart = IoAddress;
-      ConfigInfo->AccessRanges[1].RangeLength = 1;
-      ConfigInfo->AccessRanges[1].RangeInMemory = FALSE;
+      (*ConfigInfo->AccessRanges)[1].RangeStart = IoAddress;
+      (*ConfigInfo->AccessRanges)[1].RangeLength = 1;
+      (*ConfigInfo->AccessRanges)[1].RangeInMemory = FALSE;
    }
    if (BusMasterPortBase)
    {
@@ -490,9 +502,9 @@ AtapiClaimHwResources(PATAPI_MINIPORT_EXTENSION DevExt,
          return FALSE;
       }
       DevExt->BusMasterRegisterBase = (ULONG)IoBase;
-      ConfigInfo->AccessRanges[2].RangeStart = IoAddress;
-      ConfigInfo->AccessRanges[2].RangeLength = 8;
-      ConfigInfo->AccessRanges[2].RangeInMemory = FALSE;
+      (*ConfigInfo->AccessRanges)[2].RangeStart = IoAddress;
+      (*ConfigInfo->AccessRanges)[2].RangeLength = 8;
+      (*ConfigInfo->AccessRanges)[2].RangeInMemory = FALSE;
 #ifdef ENABLE_DMA
 //      ConfigInfo->DmaChannel = SP_UNINITIALIZED_VALUE;
 //      ConfigInfo->DmaPort = SP_UNINITIALIZED_VALUE;
@@ -937,6 +949,134 @@ AtapiStartIo(IN PVOID DeviceExtension,
          }
        break;
 
+      case SRB_FUNCTION_IO_CONTROL:
+        {
+          PSRB_IO_CONTROL SrbIoControl = (PSRB_IO_CONTROL)Srb->DataBuffer;
+          if (Srb->DataTransferLength < sizeof(SRB_IO_CONTROL) ||
+              Srb->DataTransferLength < SrbIoControl->Length + sizeof(SRB_IO_CONTROL))
+            {
+              Result = SRB_STATUS_INVALID_REQUEST;
+            }
+          else
+            {
+              if (!_strnicmp((char*)SrbIoControl->Signature, "ScsiDisk", 8))
+                {
+                  switch (SrbIoControl->ControlCode)
+                    {
+                      default:
+                        Result = SRB_STATUS_INVALID_REQUEST;
+                        break;
+
+                      case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
+                      case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
+                      case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
+                      case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
+                      case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
+                      case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
+                      case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
+                      case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
+                      case IOCTL_SCSI_MINIPORT_READ_SMART_LOG:
+#if 0
+                      case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG:
+#endif
+                        Result = AtapiSendSmartCommand(DevExt, Srb);
+                        break;
+
+                      case IOCTL_SCSI_MINIPORT_SMART_VERSION:
+                        {
+                          GETVERSIONINPARAMS Version;      
+                          ULONG i;
+
+                          DPRINT("IOCTL_SCSI_MINIPORT_SMART_VERSION\n");
+
+                          RtlZeroMemory(&Version, sizeof(GETVERSIONINPARAMS));
+                          Version.bVersion = 1;
+                          Version.bRevision = 1;
+                          for (i = 0; i < 2; i++)
+                            {
+                              switch (DevExt->DeviceFlags[i] & (DEVICE_PRESENT|DEVICE_ATAPI))
+                                {
+                                  case DEVICE_PRESENT:
+                                    Version.bIDEDeviceMap |= 0x01 << i;
+                                    break;
+/*
+                                  case DEVICE_PRESENT|DEVICE_ATAPI:
+                                    Version.bIDEDeviceMap |= 0x11 << i;
+                                    break;
+*/
+                                }
+                            }
+                          Version.fCapabilities = CAP_ATA_ID_CMD/*|CAP_ATAPI_ID_CMD|CAP_SMART_CMD*/;
+                          SrbIoControl->Length = min(sizeof(GETVERSIONINPARAMS), Srb->DataTransferLength - sizeof(SRB_IO_CONTROL));
+                          memcpy(SrbIoControl + 1, &Version, SrbIoControl->Length);
+                          Result = SRB_STATUS_SUCCESS;
+                          break;
+                        }
+
+                      case IOCTL_SCSI_MINIPORT_IDENTIFY:
+                        {
+                          SENDCMDOUTPARAMS OutParams;
+                          SENDCMDINPARAMS InParams = *(PSENDCMDINPARAMS)(SrbIoControl + 1);
+
+                          DPRINT("IOCTL_SCSI_MINIPORT_IDENTIFY\n");
+
+                          if (Srb->DataTransferLength < sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1)
+                            {
+                              Result = SRB_STATUS_INVALID_REQUEST;
+                              break;
+                            }
+                  
+                          RtlZeroMemory(&OutParams, sizeof(SENDCMDOUTPARAMS));
+
+                          if (InParams.irDriveRegs.bCommandReg != IDE_CMD_IDENT_ATA_DRV)
+                            {
+                              DPRINT("bCommandReg: %x\n", InParams.irDriveRegs.bCommandReg);
+                              OutParams.DriverStatus.bIDEError = 1;
+                              Result = SRB_STATUS_INVALID_REQUEST;
+                            }
+                          else if (InParams.bDriveNumber > 1 ||
+                                   (DevExt->DeviceFlags[InParams.bDriveNumber] & (DEVICE_PRESENT|DEVICE_ATAPI)) != DEVICE_PRESENT)
+                            {
+                              OutParams.DriverStatus.bIDEError = 1;
+                              Result = SRB_STATUS_NO_DEVICE;
+                            }
+                          else
+                            {
+                              Result = SRB_STATUS_SUCCESS;
+                            }
+                          if (Result == SRB_STATUS_SUCCESS)
+                            {
+                              SrbIoControl->Length = min(sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE, Srb->DataTransferLength - sizeof(SRB_IO_CONTROL));
+                            }
+                          else
+                            {
+                              SrbIoControl->Length = min(sizeof(SENDCMDOUTPARAMS) - 1, Srb->DataTransferLength - sizeof(SRB_IO_CONTROL));
+                            }
+
+                          if (SrbIoControl->Length >= sizeof(SENDCMDOUTPARAMS) - 1)
+                            {
+                              OutParams.cBufferSize = min(SrbIoControl->Length, IDENTIFY_BUFFER_SIZE);
+                            }
+                          
+                          memcpy(SrbIoControl + 1, &OutParams, min (SrbIoControl->Length, sizeof(SENDCMDOUTPARAMS) - 1));
+                         
+                          if (SrbIoControl->Length > sizeof(SENDCMDOUTPARAMS) - 1)
+                            {
+                              RtlCopyMemory((PVOID)((ULONG_PTR)(SrbIoControl + 1) + sizeof(SENDCMDOUTPARAMS) - 1), &DevExt->DeviceParams[InParams.bDriveNumber], OutParams.cBufferSize);
+                            }
+                          break;
+                        }
+                    }
+                }
+              else
+                {
+                  Result = SRB_STATUS_INVALID_REQUEST;
+                  SrbIoControl->Length = 0;
+                }
+            }
+          break;
+        }
+
       default:
        Result = SRB_STATUS_INVALID_REQUEST;
        break;
@@ -948,7 +1088,6 @@ AtapiStartIo(IN PVOID DeviceExtension,
   if (Result != SRB_STATUS_PENDING)
     {
       DevExt->CurrentSrb = NULL;
-      Srb->SrbStatus = (UCHAR)Result;
 
       ScsiPortNotification(RequestComplete,
                           DeviceExtension,
@@ -971,7 +1110,7 @@ static BOOLEAN STDCALL
 AtapiInterrupt(IN PVOID DeviceExtension)
 {
   PATAPI_MINIPORT_EXTENSION DevExt;
-  BYTE Status;
+  UCHAR Status;
   DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension;
 
   if (DevExt->Handler == NULL)
@@ -1014,7 +1153,7 @@ static BOOLEAN
 AtapiConfigDma(PATAPI_MINIPORT_EXTENSION DeviceExtension, ULONG UnitNumber)
 {
   BOOLEAN Result = FALSE;
-  BYTE Status;
+  UCHAR Status;
 
   if (UnitNumber < 2)
     {
@@ -1095,10 +1234,10 @@ AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension,
 
   DPRINT("AtapiFindDevices() called\n");
 
-  CommandPortBase = ScsiPortConvertPhysicalAddressToUlong(ConfigInfo->AccessRanges[0].RangeStart);
+  CommandPortBase = ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[0].RangeStart);
   DPRINT("  CommandPortBase: %x\n", CommandPortBase);
 
-  ControlPortBase = ScsiPortConvertPhysicalAddressToUlong(ConfigInfo->AccessRanges[1].RangeStart);
+  ControlPortBase = ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[1].RangeStart);
   DPRINT("  ControlPortBase: %x\n", ControlPortBase);
 
   for (UnitNumber = 0; UnitNumber < 2; UnitNumber++)
@@ -1173,6 +1312,17 @@ AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension,
                  DeviceExtension->DeviceFlags[UnitNumber] |= DEVICE_DMA_CMD;
                }
 #endif
+              if (!(DeviceExtension->DeviceParams[UnitNumber].SupportedFeatures83 & 0x1000) ||
+                 !(DeviceExtension->DeviceParams[UnitNumber].EnabledFeatures86 & 0x1000))
+                {
+                  DeviceExtension->DeviceFlags[UnitNumber] |= DEVICE_NO_FLUSH;                      
+                }
+
+              /* Don't flush CD/DVD drives */
+              if (((DeviceExtension->DeviceParams[UnitNumber].ConfigBits >> 8) & 0x1F) == READ_ONLY_DIRECT_ACCESS_DEVICE)
+               {
+                 DeviceExtension->DeviceFlags[UnitNumber] |= DEVICE_NO_FLUSH;
+               }
              DeviceFound = TRUE;
            }
          else
@@ -1214,6 +1364,22 @@ AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension,
                  DeviceExtension->DeviceFlags[UnitNumber] |= DEVICE_DMA_CMD;
                }
 #endif
+              if (DeviceExtension->DeviceFlags[UnitNumber] & DEVICE_48BIT_ADDRESS)
+                {
+                  if (!(DeviceExtension->DeviceParams[UnitNumber].SupportedFeatures83 & 0x2000) ||
+                     !(DeviceExtension->DeviceParams[UnitNumber].EnabledFeatures86 & 0x2000))
+                    {
+                      DeviceExtension->DeviceFlags[UnitNumber] |= DEVICE_NO_FLUSH;                      
+                    }
+                }
+              else
+                {
+                  if (!(DeviceExtension->DeviceParams[UnitNumber].SupportedFeatures83 & 0x1000) ||
+                     !(DeviceExtension->DeviceParams[UnitNumber].EnabledFeatures86 & 0x1000))
+                    {
+                      DeviceExtension->DeviceFlags[UnitNumber] |= DEVICE_NO_FLUSH;                      
+                    }
+                }
              DeviceFound = TRUE;
            }
          else
@@ -1273,6 +1439,9 @@ AtapiIdentifyDevice(IN ULONG CommandPort,
 {
   LONG i;
   ULONG mode;
+  char SerialNumber[20];
+  char FirmwareRev[8];
+  char ModelNumber[40];
 
   /*  Get the Drive Identify block from drive or die  */
   if (AtapiPolledRead(CommandPort,
@@ -1291,9 +1460,12 @@ AtapiIdentifyDevice(IN ULONG CommandPort,
     }
 
   /*  Report on drive parameters if debug mode  */
-  IDESwapBytePairs(DrvParms->SerialNumber, 20);
-  IDESwapBytePairs(DrvParms->FirmwareRev, 8);
-  IDESwapBytePairs(DrvParms->ModelNumber, 40);
+  memcpy(SerialNumber, DrvParms->SerialNumber, 20);
+  memcpy(FirmwareRev, DrvParms->FirmwareRev, 8);
+  memcpy(ModelNumber, DrvParms->ModelNumber, 40);
+  IDESwapBytePairs((PUCHAR)SerialNumber, 20);
+  IDESwapBytePairs((PUCHAR)FirmwareRev, 8);
+  IDESwapBytePairs((PUCHAR)ModelNumber, 40);
   DPRINT("Config:%04x  Cyls:%5d  Heads:%2d  Sectors/Track:%3d  Gaps:%02d %02d\n",
          DrvParms->ConfigBits,
          DrvParms->LogicalCyls,
@@ -1304,13 +1476,13 @@ AtapiIdentifyDevice(IN ULONG CommandPort,
   DPRINT("Bytes/PLO:%3d  Vendor Cnt:%2d  Serial number:[%.20s]\n",
          DrvParms->BytesInPLO,
          DrvParms->VendorUniqueCnt,
-         DrvParms->SerialNumber);
+         SerialNumber);
   DPRINT("Cntlr type:%2d  BufSiz:%5d  ECC bytes:%3d  Firmware Rev:[%.8s]\n",
          DrvParms->ControllerType,
          DrvParms->BufferSize * IDE_SECTOR_BUF_SZ,
          DrvParms->ECCByteCnt,
-         DrvParms->FirmwareRev);
-  DPRINT("Model:[%.40s]\n", DrvParms->ModelNumber);
+         FirmwareRev);
+  DPRINT("Model:[%.40s]\n", ModelNumber);
   DPRINT("RWMultMax?:%04x  RWMult?:%02x  LBA:%d  DMA:%d  MinPIO:%d ns  MinDMA:%d ns\n",
          (DrvParms->RWMultImplemented),
         (DrvParms->RWMultCurrent) & 0xff,
@@ -1598,6 +1770,219 @@ AtapiPolledRead(IN ULONG CommandPort,
 
 //  -------------------------------------------  Nondiscardable statics
 
+static ULONG
+AtapiSendSmartCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
+                     IN PSCSI_REQUEST_BLOCK Srb)
+{
+  PSRB_IO_CONTROL SrbIoControl = (PSRB_IO_CONTROL)Srb->DataBuffer;
+  SENDCMDINPARAMS InParams;
+  PSENDCMDOUTPARAMS OutParams = (PSENDCMDOUTPARAMS)(SrbIoControl + 1);
+  ULONG Retries;
+  UCHAR Status;
+
+  if (Srb->DataTransferLength < sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDOUTPARAMS) - 1 ||
+      SrbIoControl->Length < sizeof(SENDCMDOUTPARAMS) - 1)
+    {
+      return SRB_STATUS_INVALID_REQUEST;
+    }
+  InParams = *(PSENDCMDINPARAMS)(SrbIoControl + 1);
+
+  DPRINT("%02x %02x %02x %02x %02x %02x %02x %02x\n",
+         InParams.irDriveRegs.bFeaturesReg,
+         InParams.irDriveRegs.bSectorCountReg,
+         InParams.irDriveRegs.bSectorNumberReg,
+         InParams.irDriveRegs.bCylLowReg,
+         InParams.irDriveRegs.bCylHighReg,
+         InParams.irDriveRegs.bDriveHeadReg,
+         InParams.irDriveRegs.bCommandReg,
+         InParams.irDriveRegs.bReserved);
+
+  if (InParams.bDriveNumber > 1 ||
+      (DeviceExtension->DeviceFlags[InParams.bDriveNumber] & (DEVICE_PRESENT|DEVICE_ATAPI)) != DEVICE_PRESENT)
+    {
+      RtlZeroMemory(&OutParams, sizeof(SENDCMDOUTPARAMS));
+      OutParams->DriverStatus.bIDEError = 1;
+      return SRB_STATUS_NO_DEVICE;
+    }
+
+  DeviceExtension->DataTransferLength = 0;
+
+  switch (SrbIoControl->ControlCode)
+    {
+      case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
+        DPRINT("IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS\n");
+
+        if (Srb->DataTransferLength < sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDOUTPARAMS) - 1 + READ_ATTRIBUTE_BUFFER_SIZE ||
+            SrbIoControl->Length < sizeof(SENDCMDOUTPARAMS) - 1 + READ_ATTRIBUTE_BUFFER_SIZE ||
+            InParams.irDriveRegs.bFeaturesReg != READ_ATTRIBUTES ||
+            InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
+            InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
+            InParams.irDriveRegs.bCommandReg != SMART_CMD)
+          {
+            return SRB_STATUS_INVALID_REQUEST;            
+          }
+        InParams.irDriveRegs.bSectorCountReg = 0; 
+        InParams.irDriveRegs.bSectorNumberReg = 0;
+        DeviceExtension->DataTransferLength = READ_ATTRIBUTE_BUFFER_SIZE;
+        break;
+      
+      case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
+        DPRINT("IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS\n");
+
+        if (Srb->DataTransferLength < sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDOUTPARAMS) - 1 + READ_THRESHOLD_BUFFER_SIZE ||
+            SrbIoControl->Length < sizeof(SENDCMDOUTPARAMS) - 1 + READ_THRESHOLD_BUFFER_SIZE ||
+            InParams.irDriveRegs.bFeaturesReg != READ_THRESHOLDS ||
+            InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
+            InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
+            InParams.irDriveRegs.bCommandReg != SMART_CMD)
+          {
+            return SRB_STATUS_INVALID_REQUEST;            
+          }
+        InParams.irDriveRegs.bSectorCountReg = 0; 
+        InParams.irDriveRegs.bSectorNumberReg = 0;
+        DeviceExtension->DataTransferLength = READ_THRESHOLD_BUFFER_SIZE;
+        break;
+
+      case IOCTL_SCSI_MINIPORT_READ_SMART_LOG:
+        DPRINT("IOCTL_SCSI_MINIPORT_READ_SMART_LOG\n");
+
+        if (Srb->DataTransferLength < sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDOUTPARAMS) - 1 + max(1, InParams.irDriveRegs.bSectorCountReg) * SMART_LOG_SECTOR_SIZE ||
+            SrbIoControl->Length < sizeof(SENDCMDOUTPARAMS) - 1 + max(1, InParams.irDriveRegs.bSectorCountReg) * SMART_LOG_SECTOR_SIZE ||
+            InParams.irDriveRegs.bFeaturesReg != SMART_READ_LOG ||
+            InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
+            InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
+            InParams.irDriveRegs.bCommandReg != SMART_CMD)
+          {
+            return SRB_STATUS_INVALID_REQUEST;            
+          }
+        DeviceExtension->DataTransferLength = max(1, InParams.irDriveRegs.bSectorCountReg) * SMART_LOG_SECTOR_SIZE;
+        break;
+
+      case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
+        DPRINT("IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE\n");
+
+        if (InParams.irDriveRegs.bFeaturesReg != ENABLE_DISABLE_AUTOSAVE ||
+            (InParams.irDriveRegs.bSectorCountReg != 0 && InParams.irDriveRegs.bSectorCountReg != 1) || 
+            InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
+            InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
+            InParams.irDriveRegs.bCommandReg != SMART_CMD)
+          {
+            return SRB_STATUS_INVALID_REQUEST;            
+          }
+        InParams.irDriveRegs.bSectorNumberReg = 0;
+        break;
+
+      case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
+        DPRINT("IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES\n");
+
+        if (InParams.irDriveRegs.bFeaturesReg != SAVE_ATTRIBUTE_VALUES ||
+            (InParams.irDriveRegs.bSectorCountReg != 0 && InParams.irDriveRegs.bSectorCountReg != 0xf1) || 
+            InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
+            InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
+            InParams.irDriveRegs.bCommandReg != SMART_CMD)
+          {
+            return SRB_STATUS_INVALID_REQUEST;            
+          }
+        InParams.irDriveRegs.bSectorNumberReg = 0;
+        break;
+
+      case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
+        DPRINT("IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS\n");
+
+        if (InParams.irDriveRegs.bFeaturesReg != EXECUTE_OFFLINE_DIAGS ||
+            InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
+            InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
+            InParams.irDriveRegs.bCommandReg != SMART_CMD)
+          {
+            return SRB_STATUS_INVALID_REQUEST;            
+          }
+        InParams.irDriveRegs.bSectorCountReg = 0; 
+        break;
+
+      case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
+        DPRINT("IOCTL_SCSI_MINIPORT_ENABLE_SMART\n");
+
+        if (InParams.irDriveRegs.bFeaturesReg != ENABLE_SMART ||
+            InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
+            InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
+            InParams.irDriveRegs.bCommandReg != SMART_CMD)
+          {
+            return SRB_STATUS_INVALID_REQUEST;            
+          }
+        InParams.irDriveRegs.bSectorCountReg = 0; 
+        InParams.irDriveRegs.bSectorNumberReg = 0;
+        break;
+
+      case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
+        DPRINT("IOCTL_SCSI_MINIPORT_DISABLE_SMART\n");
+
+        if (InParams.irDriveRegs.bFeaturesReg != DISABLE_SMART ||
+            InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
+            InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
+            InParams.irDriveRegs.bCommandReg != SMART_CMD)
+          {
+            return SRB_STATUS_INVALID_REQUEST;            
+          }
+        InParams.irDriveRegs.bSectorCountReg = 0; 
+        InParams.irDriveRegs.bSectorNumberReg = 0;
+        break;
+
+      case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
+        DPRINT("IOCTL_SCSI_MINIPORT_RETURN_STATUS\n");
+
+        if (InParams.irDriveRegs.bFeaturesReg != RETURN_SMART_STATUS ||
+            InParams.irDriveRegs.bCylLowReg != SMART_CYL_LOW ||
+            InParams.irDriveRegs.bCylHighReg != SMART_CYL_HI ||
+            InParams.irDriveRegs.bCommandReg != SMART_CMD)
+          {
+            return SRB_STATUS_INVALID_REQUEST;            
+          }
+        InParams.irDriveRegs.bSectorCountReg = 0; 
+        InParams.irDriveRegs.bSectorNumberReg = 0;
+        break;
+    }
+
+  Srb->TargetId = InParams.bDriveNumber;
+  
+  /* Set pointer to data buffer. */
+  DeviceExtension->DataBuffer = (PUCHAR)OutParams->bBuffer;
+
+  DeviceExtension->CurrentSrb = Srb;
+
+  /*  wait for BUSY to clear  */
+  for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
+    {
+      Status = IDEReadStatus(DeviceExtension->CommandPortBase);
+      if (!(Status & IDE_SR_BUSY))
+        {
+          break;
+        }
+      ScsiPortStallExecution(10);
+    }
+  if (Retries >= IDE_MAX_BUSY_RETRIES)
+    {
+      DPRINT ("Drive is BUSY for too long\n");
+      return(SRB_STATUS_BUSY);
+    }
+
+  /*  Select the desired drive  */
+  InParams.irDriveRegs.bDriveHeadReg = (InParams.bDriveNumber ? IDE_DH_DRV1 : IDE_DH_DRV0) | IDE_DH_FIXED;
+  IDEWriteDriveHead(DeviceExtension->CommandPortBase, InParams.irDriveRegs.bDriveHeadReg);
+  ScsiPortStallExecution(2);
+
+  IDEWritePrecomp(DeviceExtension->CommandPortBase, InParams.irDriveRegs.bFeaturesReg);
+  IDEWriteSectorCount(DeviceExtension->CommandPortBase, InParams.irDriveRegs.bSectorCountReg);
+  IDEWriteSectorNum(DeviceExtension->CommandPortBase, InParams.irDriveRegs.bSectorNumberReg);
+  IDEWriteCylinderLow(DeviceExtension->CommandPortBase, InParams.irDriveRegs.bCylLowReg);
+  IDEWriteCylinderHigh(DeviceExtension->CommandPortBase, InParams.irDriveRegs.bCylHighReg);
+
+  AtapiExecuteCommand(DeviceExtension, InParams.irDriveRegs.bCommandReg, AtapiSmartInterrupt);
+
+  /* Wait for interrupt. */
+  return SRB_STATUS_PENDING;
+
+}
+
 static ULONG
 AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
                      IN PSCSI_REQUEST_BLOCK Srb)
@@ -1775,7 +2160,7 @@ AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
 #ifdef ENABLE_DMA
   if (DeviceExtension->UseDma)
     {
-      BYTE DmaCommand;
+      UCHAR DmaCommand;
       /* start DMA */
       DmaCommand = IDEReadDMACommand(DeviceExtension->BusMasterRegisterBase);
       IDEWriteDMACommand(DeviceExtension->BusMasterRegisterBase, DmaCommand|0x01);
@@ -1878,7 +2263,6 @@ AtapiInquiry(PATAPI_MINIPORT_EXTENSION DeviceExtension,
 {
   PIDE_DRIVE_IDENTIFY DeviceParams;
   PINQUIRYDATA InquiryData;
-  ULONG i;
 
   DPRINT("SCSIOP_INQUIRY: DeviceExtension %p  TargetId: %lu\n",
         DeviceExtension, Srb->TargetId);
@@ -1887,10 +2271,7 @@ AtapiInquiry(PATAPI_MINIPORT_EXTENSION DeviceExtension,
   DeviceParams = &DeviceExtension->DeviceParams[Srb->TargetId];
 
   /* clear buffer */
-  for (i = 0; i < Srb->DataTransferLength; i++)
-    {
-      ((PUCHAR)Srb->DataBuffer)[i] = 0;
-    }
+  memset(Srb->DataBuffer, 0, Srb->DataTransferLength);
 
   /* set device class */
   if (DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_ATAPI)
@@ -1898,12 +2279,6 @@ AtapiInquiry(PATAPI_MINIPORT_EXTENSION DeviceExtension,
       /* get it from the ATAPI configuration word */
       InquiryData->DeviceType = (DeviceParams->ConfigBits >> 8) & 0x1F;
       DPRINT("Device class: %u\n", InquiryData->DeviceType);
-
-      /* Don't flush CD/DVD drives */
-      if (InquiryData->DeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE)
-       {
-         DeviceExtension->DeviceFlags[Srb->TargetId] |= DEVICE_NO_FLUSH;
-       }
     }
   else
     {
@@ -1918,26 +2293,13 @@ AtapiInquiry(PATAPI_MINIPORT_EXTENSION DeviceExtension,
       InquiryData->RemovableMedia = 1;
     }
 
-  for (i = 0; i < 20; i += 2)
-    {
-      InquiryData->VendorId[i] =
-       ((PUCHAR)DeviceParams->ModelNumber)[i];
-      InquiryData->VendorId[i+1] =
-       ((PUCHAR)DeviceParams->ModelNumber)[i+1];
-    }
+  memcpy(InquiryData->VendorId, DeviceParams->ModelNumber, 20);
+  IDESwapBytePairs(InquiryData->VendorId, 20);
 
-  for (i = 0; i < 4; i++)
-    {
-      InquiryData->ProductId[12+i] = ' ';
-    }
+  memcpy(&InquiryData->ProductId[12], "    ", 4);
 
-  for (i = 0; i < 4; i += 2)
-    {
-      InquiryData->ProductRevisionLevel[i] =
-       ((PUCHAR)DeviceParams->FirmwareRev)[i];
-      InquiryData->ProductRevisionLevel[i+1] =
-       ((PUCHAR)DeviceParams->FirmwareRev)[i+1];
-    }
+  memcpy(InquiryData->ProductRevisionLevel, DeviceParams->FirmwareRev, 4);
+  IDESwapBytePairs(InquiryData->ProductRevisionLevel, 4);
 
   InquiryData->AdditionalLength = 31;
 
@@ -2024,7 +2386,7 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
   UCHAR Command;
   ULONG Retries;
   UCHAR Status;
-  BOOLEAN FASTCALL (*Handler)(PATAPI_MINIPORT_EXTENSION DevExt);
+  BOOLEAN (FASTCALL *Handler)(PATAPI_MINIPORT_EXTENSION DevExt);
 
   DPRINT("AtapiReadWrite() called!\n");
   DPRINT("SCSIOP_WRITE: TargetId: %lu\n",
@@ -2055,7 +2417,7 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
       CylinderLow[1] = 0;
       CylinderHigh[1] = 0;
       DrvHead = (Srb->TargetId ? IDE_DH_DRV1 : 0) | IDE_DH_LBA;
-
+#if 0
       DPRINT("%s:BUS=%04x:DRV=%d:LBA48=1:BLK=%08d:SC=%02x:CM=%02x\n",
             (Srb->SrbFlags & SRB_FLAGS_DATA_IN) ? "READ" : "WRITE",
             DeviceExtension->CommandPortBase,
@@ -2064,12 +2426,16 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
             (CylinderHigh[0] << 16) + (CylinderLow[0] << 8) + DectorNumberLow[0],
             SectorCount,
             Command);
+#endif
     }
   else if (DeviceParams->Capabilities & IDE_DRID_LBA_SUPPORTED)
     {
       SectorNumber[0] = StartingSector & 0xff;
       CylinderLow[0] = (StartingSector >> 8) & 0xff;
       CylinderHigh[0] = (StartingSector >> 16) & 0xff;
+      SectorNumber[1] = 0;
+      CylinderLow[1] = 0;
+      CylinderHigh[1] = 0;
       DrvHead = ((StartingSector >> 24) & 0x0f) |
                  (Srb->TargetId ? IDE_DH_DRV1 : 0) |
                 IDE_DH_LBA;
@@ -2092,6 +2458,9 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
       StartingSector /= DeviceParams->LogicalHeads;
       CylinderLow[0] = StartingSector & 0xff;
       CylinderHigh[0] = StartingSector >> 8;
+      SectorNumber[1] = 0;
+      CylinderLow[1] = 0;
+      CylinderHigh[1] = 0;
 
       DPRINT("%s:BUS=%04x:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n",
              (Srb->SrbFlags & SRB_FLAGS_DATA_IN) ? "READ" : "WRITE",
@@ -2169,8 +2538,6 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
   IDEWriteCylinderLow(DeviceExtension->CommandPortBase, CylinderLow[0]);
   IDEWriteCylinderHigh(DeviceExtension->CommandPortBase, CylinderHigh[0]);
 
-  IDEWriteDriveHead(DeviceExtension->CommandPortBase, IDE_DH_FIXED | DrvHead);
-
 #ifdef ENABLE_DMA
   if (DeviceExtension->PRDTable &&
       DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_DMA_CMD)
@@ -2222,7 +2589,7 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
 #ifdef ENABLE_DMA
   if (DeviceExtension->UseDma)
     {
-      BYTE DmaCommand;
+      UCHAR DmaCommand;
       /* start DMA */
       DmaCommand = IDEReadDMACommand(DeviceExtension->BusMasterRegisterBase);
       IDEWriteDMACommand(DeviceExtension->BusMasterRegisterBase, DmaCommand|0x01);
@@ -2239,7 +2606,7 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
           /* Wait for controller ready */
           for (Retries = 0; Retries < IDE_MAX_WRITE_RETRIES; Retries++)
            {
-             BYTE  Status = IDEReadStatus(DeviceExtension->CommandPortBase);
+             UCHAR  Status = IDEReadStatus(DeviceExtension->CommandPortBase);
              if (!(Status & IDE_SR_BUSY) || (Status & IDE_SR_ERR))
                {
                  break;
@@ -2306,12 +2673,8 @@ AtapiFlushCache(PATAPI_MINIPORT_EXTENSION DeviceExtension,
        * it doesn't make sense to flush cache on devices we don't
        * write to.
        */
-      return SRB_STATUS_INVALID_REQUEST;
-    }
-
-  if (!(DeviceExtension->DeviceParams[Srb->TargetId].SupportedFeatures83 & 0x1000))
-    {
-      /* The device states it doesn't support the command */
+       
+      /* The device states it doesn't support the command or it is disabled */      
       DPRINT("The drive doesn't support FLUSH_CACHE\n");
       return SRB_STATUS_INVALID_REQUEST;
     }
@@ -2344,22 +2707,6 @@ AtapiFlushCache(PATAPI_MINIPORT_EXTENSION DeviceExtension,
                      DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_48BIT_ADDRESS ? IDE_CMD_FLUSH_CACHE_EXT : IDE_CMD_FLUSH_CACHE,
                      AtapiNoDataInterrupt);
 
-  /* Wait for controller ready */
-  for (Retries = 0; Retries < IDE_MAX_WRITE_RETRIES; Retries++)
-    {
-      Status = IDEReadStatus(DeviceExtension->CommandPortBase);
-      if (!(Status & IDE_SR_BUSY) || (Status & IDE_SR_ERR))
-       {
-         break;
-       }
-      ScsiPortStallExecution(10);
-    }
-  if (Retries >= IDE_MAX_WRITE_RETRIES)
-    {
-      DPRINT1("Drive is BUSY for too long after sending write command\n");
-      DeviceExtension->Handler = NULL;
-      return(SRB_STATUS_BUSY);
-    }
 
   DPRINT("AtapiFlushCache() done!\n");
 
@@ -2646,12 +2993,12 @@ AtapiCompleteRequest(PATAPI_MINIPORT_EXTENSION DevExt,
 static BOOLEAN FASTCALL
 AtapiDmaPacketInterrupt(PATAPI_MINIPORT_EXTENSION DevExt)
 {
-  BYTE SrbStatus;
-  BYTE DmaCommand;
-  BYTE DmaStatus;
-  BYTE Status;
-  BYTE Error;
-  BYTE SensKey;
+  UCHAR SrbStatus;
+  UCHAR DmaCommand;
+  UCHAR DmaStatus;
+  UCHAR Status;
+  UCHAR Error;
+  UCHAR SensKey;
 
   DPRINT("AtapiPacketDmaInterrupt\n");
 
@@ -2700,16 +3047,16 @@ static BOOLEAN FASTCALL
 AtapiPacketInterrupt(PATAPI_MINIPORT_EXTENSION DevExt)
 {
   PSCSI_REQUEST_BLOCK Srb;
-  BYTE Status;
-  BYTE IntReason;
+  UCHAR Status;
+  UCHAR IntReason;
   ULONG TransferSize;
   ULONG JunkSize = 0;
-  BOOL IsLastBlock;
-  PBYTE TargetAddress;
+  BOOLEAN IsLastBlock;
+  PUCHAR TargetAddress;
   ULONG Retries;
-  BYTE SrbStatus;
-  BYTE Error;
-  BYTE SensKey;
+  UCHAR SrbStatus;
+  UCHAR Error;
+  UCHAR SensKey;
 
   DPRINT("AtapiPacketInterrupt()\n");
 
@@ -2840,7 +3187,7 @@ AtapiPacketInterrupt(PATAPI_MINIPORT_EXTENSION DevExt)
 static BOOLEAN FASTCALL
 AtapiNoDataInterrupt(PATAPI_MINIPORT_EXTENSION DevExt)
 {
-  BYTE Status;
+  UCHAR Status;
 
   DPRINT("AtapiNoDataInterrupt()\n");
 
@@ -2856,9 +3203,9 @@ AtapiNoDataInterrupt(PATAPI_MINIPORT_EXTENSION DevExt)
 static BOOLEAN FASTCALL
 AtapiDmaInterrupt(PATAPI_MINIPORT_EXTENSION DevExt)
 {
-  BYTE DmaCommand;
-  BYTE DmaStatus;
-  BYTE Status;
+  UCHAR DmaCommand;
+  UCHAR DmaStatus;
+  UCHAR Status;
 
   DPRINT("AtapiDmaInterrupt()\n");
 
@@ -2888,6 +3235,79 @@ AtapiDmaInterrupt(PATAPI_MINIPORT_EXTENSION DevExt)
 }
 #endif
 
+static BOOLEAN FASTCALL
+AtapiSmartInterrupt(PATAPI_MINIPORT_EXTENSION DevExt)
+{
+  PSCSI_REQUEST_BLOCK Srb;
+  UCHAR DeviceStatus;
+  PSRB_IO_CONTROL SrbIoControl;
+  PSENDCMDOUTPARAMS OutParams;
+  PIDEREGS IdeRegs;
+
+  DPRINT("AtapiSmartInterrupt() called!\n");
+
+  Srb = DevExt->CurrentSrb;
+
+
+  DeviceStatus = IDEReadStatus(DevExt->CommandPortBase);
+  if ((DeviceStatus & (IDE_SR_DRQ|IDE_SR_BUSY|IDE_SR_ERR)) != (DevExt->DataTransferLength ? IDE_SR_DRQ : 0))
+    {
+      if (DeviceStatus & (IDE_SR_ERR|IDE_SR_DRQ))
+        {
+         AtapiCompleteRequest(DevExt, SRB_STATUS_ERROR);
+          DPRINT("AtapiSmartInterrupt() done!\n");
+         return TRUE;
+        }
+      DPRINT("AtapiSmartInterrupt() done!\n");
+      return FALSE;
+    }
+
+  DPRINT("CommandPortBase: %lx  ControlPortBase: %lx\n", DevExt->CommandPortBase, DevExt->ControlPortBase);
+
+  if (DevExt->DataTransferLength)
+    {
+      IDEReadBlock(DevExt->CommandPortBase, DevExt->DataBuffer, 512);
+      DevExt->DataTransferLength -= 512;
+      DevExt->DataBuffer += 512;
+    }
+
+  if (DevExt->DataTransferLength == 0)
+    {
+      SrbIoControl = (PSRB_IO_CONTROL)Srb->DataBuffer;
+      OutParams = (PSENDCMDOUTPARAMS)(SrbIoControl + 1);
+
+      OutParams->DriverStatus.bDriverError = 0;
+      OutParams->DriverStatus.bIDEError = 0;
+
+      if (SrbIoControl->ControlCode == IOCTL_SCSI_MINIPORT_RETURN_STATUS)
+        {
+          IdeRegs = (PIDEREGS)OutParams->bBuffer;
+
+          IdeRegs->bFeaturesReg = RETURN_SMART_STATUS;
+          IdeRegs->bSectorCountReg = IDEReadSectorCount(DevExt->CommandPortBase);
+          IdeRegs->bSectorNumberReg = IDEReadSectorNum(DevExt->CommandPortBase);
+          IdeRegs->bCylLowReg = IDEReadCylinderLow(DevExt->CommandPortBase);
+          IdeRegs->bCylHighReg = IDEReadCylinderHigh(DevExt->CommandPortBase);
+          IdeRegs->bDriveHeadReg = IDEReadDriveHead(DevExt->CommandPortBase);
+          IdeRegs->bCommandReg = SMART_CMD;
+          IdeRegs->bReserved = 0;
+
+          OutParams->cBufferSize = 8;
+        }
+      else
+        {
+          OutParams->cBufferSize = DevExt->DataBuffer - OutParams->bBuffer;
+        }
+
+      AtapiCompleteRequest(DevExt, SRB_STATUS_SUCCESS);
+    }
+
+  DPRINT("AtapiSmartInterrupt() done!\n");
+
+  return(TRUE);
+}
+
+
 static BOOLEAN FASTCALL
 AtapiReadInterrupt(PATAPI_MINIPORT_EXTENSION DevExt)
 {
@@ -3032,8 +3452,8 @@ AtapiWriteInterrupt(IN PATAPI_MINIPORT_EXTENSION DevExt)
 
 static VOID
 AtapiExecuteCommand(PATAPI_MINIPORT_EXTENSION DevExt,
-                   BYTE command,
-                   BOOLEAN FASTCALL (*Handler)(PATAPI_MINIPORT_EXTENSION))
+                   UCHAR command,
+                   BOOLEAN (FASTCALL *Handler)(PATAPI_MINIPORT_EXTENSION))
 {
   if (DevExt->Handler != NULL)
     {
@@ -3048,7 +3468,7 @@ AtapiExecuteCommand(PATAPI_MINIPORT_EXTENSION DevExt,
 static BOOLEAN
 AtapiInitDma(PATAPI_MINIPORT_EXTENSION DevExt,
             PSCSI_REQUEST_BLOCK Srb,
-            BYTE cmd)
+            UCHAR cmd)
 {
   PVOID StartAddress;
   PVOID EndAddress;
@@ -3056,12 +3476,12 @@ AtapiInitDma(PATAPI_MINIPORT_EXTENSION DevExt,
   SCSI_PHYSICAL_ADDRESS PhysicalAddress;
   ULONG Length;
   ULONG tmpLength;
-  BYTE Status;
+  UCHAR Status;
 
   DPRINT("AtapiInitDma()\n");
 
   StartAddress = Srb->DataBuffer;
-  EndAddress = StartAddress + Srb->DataTransferLength;
+  EndAddress = (PVOID)((ULONG_PTR)StartAddress + Srb->DataTransferLength);
   DevExt->PRDCount = 0;
 
   while (StartAddress < EndAddress)
@@ -3100,7 +3520,7 @@ AtapiInitDma(PATAPI_MINIPORT_EXTENSION DevExt,
                  return FALSE;
                }
               PhysicalAddress.u.LowPart += tmpLength;
-             StartAddress += tmpLength;
+             StartAddress = (PVOID)((ULONG_PTR)StartAddress + tmpLength);
              Length -= tmpLength;
              PRDEntry->PhysAddress = PhysicalAddress.u.LowPart;
            }
@@ -3109,7 +3529,7 @@ AtapiInitDma(PATAPI_MINIPORT_EXTENSION DevExt,
          PRDEntry->PhysAddress = PhysicalAddress.u.LowPart;
           PRDEntry->Length = tmpLength;
           PRDEntry++;
-          StartAddress += tmpLength;
+          StartAddress = (PVOID)((ULONG_PTR)StartAddress + tmpLength);
           PhysicalAddress.u.LowPart += tmpLength;
          Length -= tmpLength;
        }