Added more stuff to the IDENTIFY data block.
authorEric Kohl <eric.kohl@reactos.org>
Tue, 24 Jun 2003 12:29:02 +0000 (12:29 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Tue, 24 Jun 2003 12:29:02 +0000 (12:29 +0000)
Added support for the TEST UNIT READY command.
Combined various booleans in a flags variable.

svn path=/trunk/; revision=4957

reactos/drivers/storage/atapi/atapi.c
reactos/drivers/storage/atapi/atapi.h

index 5ebea83..04e6a3c 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: atapi.c,v 1.38 2003/04/06 10:45:15 chorns Exp $
+/* $Id: atapi.c,v 1.39 2003/06/24 12:29:02 ekohl Exp $
  *
  * COPYRIGHT:   See COPYING in the top level directory
  * PROJECT:     ReactOS ATAPI miniport driver
 typedef struct _ATAPI_MINIPORT_EXTENSION
 {
   IDE_DRIVE_IDENTIFY DeviceParams[2];
-  BOOLEAN DevicePresent[2];
-  BOOLEAN DeviceAtapi[2];
-  ULONG TransferSize[2]; 
-  BOOLEAN MultiSectorCommand[2];
-  BOOLEAN DWordIo[2];
-
+  ULONG DeviceFlags[2];
+  ULONG TransferSize[2];
 
   ULONG CommandPortBase;
   ULONG ControlPortBase;
@@ -93,6 +89,14 @@ typedef struct _ATAPI_MINIPORT_EXTENSION
   ULONG DataTransferLength;
 } ATAPI_MINIPORT_EXTENSION, *PATAPI_MINIPORT_EXTENSION;
 
+/* DeviceFlags */
+#define DEVICE_PRESENT           0x00000001
+#define DEVICE_ATAPI             0x00000002
+#define DEVICE_MULTI_SECTOR_CMD  0x00000004
+#define DEVICE_DWORD_IO          0x00000008
+#define DEVICE_48BIT_ADDRESS     0x00000010
+#define DEVICE_MEDIA_STATUS      0x00000020
+
 
 typedef struct _UNIT_EXTENSION
 {
@@ -237,6 +241,10 @@ static ULONG
 AtapiFlushCache(PATAPI_MINIPORT_EXTENSION DeviceExtension,
                PSCSI_REQUEST_BLOCK Srb);
 
+static ULONG
+AtapiTestUnitReady(PATAPI_MINIPORT_EXTENSION DeviceExtension,
+                  PSCSI_REQUEST_BLOCK Srb);
+
 static UCHAR
 AtapiErrorToScsi(PVOID DeviceExtension,
                 PSCSI_REQUEST_BLOCK Srb);
@@ -830,7 +838,7 @@ AtapiStartIo(IN PVOID DeviceExtension,
     {
       case SRB_FUNCTION_EXECUTE_SCSI:
        DevExt->CurrentSrb = Srb;
-       if (DevExt->DeviceAtapi[Srb->TargetId] == TRUE)
+       if (DevExt->DeviceFlags[Srb->TargetId] & DEVICE_ATAPI)
          {
            Result = AtapiSendAtapiCommand(DevExt,
                                           Srb);
@@ -915,7 +923,7 @@ AtapiInterrupt(IN PVOID DeviceExtension)
 
   DPRINT("CommandPortBase: %lx  ControlPortBase: %lx\n", CommandPortBase, ControlPortBase);
 
-  IsAtapi = DevExt->DeviceAtapi[Srb->TargetId];
+  IsAtapi = (DevExt->DeviceFlags[Srb->TargetId] & DEVICE_ATAPI);
   DPRINT("IsAtapi == %s\n", (IsAtapi) ? "TRUE" : "FALSE");
 
   IsLastBlock = FALSE;
@@ -974,22 +982,23 @@ AtapiInterrupt(IN PVOID DeviceExtension)
               !(IDEReadStatus(CommandPortBase) & IDE_SR_DRQ);
               Retries++)
            {
-               KeStallExecutionProcessor(10);
+             KeStallExecutionProcessor(10);
            }
 
          /* Copy the block of data */
-         if (DevExt->DWordIo[Srb->TargetId])
-         {
-            IDEReadBlock32(CommandPortBase,
-                           TargetAddress,
-                           TransferSize);
-         }
+         if (DevExt->DeviceFlags[Srb->TargetId] & DEVICE_DWORD_IO)
+           {
+             IDEReadBlock32(CommandPortBase,
+                            TargetAddress,
+                            TransferSize);
+           }
          else
-         {
-            IDEReadBlock(CommandPortBase,
-                         TargetAddress,
-                         TransferSize);
-         }
+           {
+             IDEReadBlock(CommandPortBase,
+                          TargetAddress,
+                          TransferSize);
+           }
+
          /* check DRQ */
          if (IsLastBlock)
            {
@@ -1034,27 +1043,27 @@ AtapiInterrupt(IN PVOID DeviceExtension)
              /* Update DevExt data */
              TransferSize = DevExt->TransferSize[Srb->TargetId];
              if (DevExt->DataTransferLength < TransferSize)
-             {
-                TransferSize = DevExt->DataTransferLength;
-             }
-                
+               {
+                 TransferSize = DevExt->DataTransferLength;
+               }
+
              TargetAddress = DevExt->DataBuffer;
              DevExt->DataBuffer += TransferSize;
              DevExt->DataTransferLength -= TransferSize;
 
              /* Write the sector */
-              if (DevExt->DWordIo[Srb->TargetId])
-             {
-                IDEWriteBlock32(CommandPortBase,
-                                TargetAddress,
-                                TransferSize);
-             }
+             if (DevExt->DeviceFlags[Srb->TargetId] & DEVICE_DWORD_IO)
+               {
+                 IDEWriteBlock32(CommandPortBase,
+                                 TargetAddress,
+                                 TransferSize);
+               }
              else
-             {
-                IDEWriteBlock(CommandPortBase,
-                              TargetAddress,
-                              TransferSize);
-             }
+               {
+                 IDEWriteBlock(CommandPortBase,
+                               TargetAddress,
+                               TransferSize);
+               }
            }
 
          Srb->SrbStatus = SRB_STATUS_SUCCESS;
@@ -1179,7 +1188,7 @@ AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension,
       if (Retries >= 20000)
        {
          DPRINT("Timeout on drive %lu\n", UnitNumber);
-         DeviceExtension->DevicePresent[UnitNumber] = FALSE;
+         DeviceExtension->DeviceFlags[UnitNumber] &= ~DEVICE_PRESENT;
          continue;
        }
 
@@ -1200,11 +1209,10 @@ AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension,
                                  &DeviceExtension->DeviceParams[UnitNumber]))
            {
              DPRINT("  ATAPI drive found!\n");
-             DeviceExtension->DevicePresent[UnitNumber] = TRUE;
-             DeviceExtension->DeviceAtapi[UnitNumber] = TRUE;
-             DeviceExtension->TransferSize[UnitNumber] = DeviceExtension->DeviceParams[UnitNumber].BytesPerSector;
-              DeviceExtension->MultiSectorCommand[UnitNumber] = FALSE;
-              DeviceExtension->DWordIo[UnitNumber] = FALSE;
+             DeviceExtension->DeviceFlags[UnitNumber] |= DEVICE_PRESENT;
+             DeviceExtension->DeviceFlags[UnitNumber] |= DEVICE_ATAPI;
+             DeviceExtension->TransferSize[UnitNumber] =
+               DeviceExtension->DeviceParams[UnitNumber].BytesPerSector;
              DeviceFound = TRUE;
            }
          else
@@ -1221,22 +1229,22 @@ AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension,
                                  &DeviceExtension->DeviceParams[UnitNumber]))
            {
              DPRINT("  IDE drive found!\n");
-             DeviceExtension->DevicePresent[UnitNumber] = TRUE;
-             DeviceExtension->DeviceAtapi[UnitNumber] = FALSE;
+             DeviceExtension->DeviceFlags[UnitNumber] |= DEVICE_PRESENT;
              DeviceExtension->TransferSize[UnitNumber] = DeviceExtension->DeviceParams[UnitNumber].BytesPerSector;
              if ((DeviceExtension->DeviceParams[UnitNumber].RWMultImplemented & 0x8000) && 
                  (DeviceExtension->DeviceParams[UnitNumber].RWMultImplemented & 0xff) &&
                  (DeviceExtension->DeviceParams[UnitNumber].RWMultCurrent & 0x100) &&
                  (DeviceExtension->DeviceParams[UnitNumber].RWMultCurrent & 0xff))
-             {
-                DeviceExtension->TransferSize[UnitNumber] *= (DeviceExtension->DeviceParams[UnitNumber].RWMultCurrent & 0xff);
-                DeviceExtension->MultiSectorCommand[UnitNumber] = TRUE;
-             }
-             else
-             {
-                 DeviceExtension->MultiSectorCommand[UnitNumber] = FALSE;
-             }
-              DeviceExtension->DWordIo[UnitNumber] = DeviceExtension->DeviceParams[UnitNumber].DWordIo ? TRUE : FALSE;
+               {
+                 DeviceExtension->TransferSize[UnitNumber] *= (DeviceExtension->DeviceParams[UnitNumber].RWMultCurrent & 0xff);
+                 DeviceExtension->DeviceFlags[UnitNumber] |= DEVICE_MULTI_SECTOR_CMD;
+               }
+
+             if (DeviceExtension->DeviceParams[UnitNumber].DWordIo)
+               {
+                 DeviceExtension->DeviceFlags[UnitNumber] |= DEVICE_DWORD_IO;
+               }
+
              DeviceFound = TRUE;
            }
          else
@@ -1677,7 +1685,7 @@ AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
       return(SRB_STATUS_INVALID_LUN);
     }
 
-  if (DeviceExtension->DevicePresent[Srb->TargetId] == FALSE)
+  if (!(DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_PRESENT))
     {
       Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
       return(SRB_STATUS_NO_DEVICE);
@@ -1823,8 +1831,12 @@ AtapiSendIdeCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
                                    Srb);
        break;
 
-      case SCSIOP_MODE_SENSE:
       case SCSIOP_TEST_UNIT_READY:
+       SrbStatus = AtapiTestUnitReady(DeviceExtension,
+                                      Srb);
+       break;
+
+      case SCSIOP_MODE_SENSE:
       case SCSIOP_VERIFY:
       case SCSIOP_START_STOP_UNIT:
       case SCSIOP_REQUEST_SENSE:
@@ -1872,7 +1884,7 @@ AtapiInquiry(PATAPI_MINIPORT_EXTENSION DeviceExtension,
       return(SRB_STATUS_INVALID_LUN);
     }
 
-  if (DeviceExtension->DevicePresent[Srb->TargetId] == FALSE)
+  if (!(DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_PRESENT))
     {
       Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
       return(SRB_STATUS_NO_DEVICE);
@@ -1888,17 +1900,17 @@ AtapiInquiry(PATAPI_MINIPORT_EXTENSION DeviceExtension,
     }
 
   /* set device class */
-  if (DeviceExtension->DeviceAtapi[Srb->TargetId] == FALSE)
-    {
-      /* hard-disk */
-      InquiryData->DeviceType = DIRECT_ACCESS_DEVICE;
-    }
-  else
+  if (DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_ATAPI)
     {
       /* get it from the ATAPI configuration word */
       InquiryData->DeviceType = (DeviceParams->ConfigBits >> 8) & 0x1F;
       DPRINT("Device class: %u\n", InquiryData->DeviceType);
     }
+  else
+    {
+      /* hard-disk */
+      InquiryData->DeviceType = DIRECT_ACCESS_DEVICE;
+    }
 
   DPRINT("ConfigBits: 0x%x\n", DeviceParams->ConfigBits);
   if (DeviceParams->ConfigBits & 0x80)
@@ -1963,7 +1975,7 @@ AtapiReadCapacity(PATAPI_MINIPORT_EXTENSION DeviceExtension,
       return(SRB_STATUS_INVALID_LUN);
     }
 
-  if (DeviceExtension->DevicePresent[Srb->TargetId] == FALSE)
+  if (!(DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_PRESENT))
     {
       Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
       return(SRB_STATUS_NO_DEVICE);
@@ -2038,7 +2050,7 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
       return(SRB_STATUS_INVALID_LUN);
     }
 
-  if (DeviceExtension->DevicePresent[Srb->TargetId] == FALSE)
+  if (!(DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_PRESENT))
     {
       Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
       return(SRB_STATUS_NO_DEVICE);
@@ -2086,11 +2098,11 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
 
   if (Srb->SrbFlags & SRB_FLAGS_DATA_IN)
     {
-      Command = DeviceExtension->MultiSectorCommand[Srb->TargetId] ? IDE_CMD_READ_MULTIPLE : IDE_CMD_READ;
+      Command = (DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_MULTI_SECTOR_CMD) ? IDE_CMD_READ_MULTIPLE : IDE_CMD_READ;
     }
   else
     {
-      Command = DeviceExtension->MultiSectorCommand[Srb->TargetId] ? IDE_CMD_WRITE_MULTIPLE : IDE_CMD_WRITE;
+      Command = (DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_MULTI_SECTOR_CMD) ? IDE_CMD_WRITE_MULTIPLE : IDE_CMD_WRITE;
     }
 
   if (DrvHead & IDE_DH_LBA)
@@ -2205,27 +2217,27 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
       /* Update DeviceExtension data */
       TransferSize = DeviceExtension->TransferSize[Srb->TargetId];
       if (DeviceExtension->DataTransferLength < TransferSize)
-      {
-        TransferSize = DeviceExtension->DataTransferLength;
-      }
+       {
+         TransferSize = DeviceExtension->DataTransferLength;
+       }
 
       TargetAddress = DeviceExtension->DataBuffer;
       DeviceExtension->DataBuffer += TransferSize;
       DeviceExtension->DataTransferLength -= TransferSize;
 
       /* Write data block */
-      if (DeviceExtension->DWordIo[Srb->TargetId])
-      {
-         IDEWriteBlock32(DeviceExtension->CommandPortBase,
-                        TargetAddress,
-                        TransferSize);
-      }
+      if (DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_DWORD_IO)
+       {
+         IDEWriteBlock32(DeviceExtension->CommandPortBase,
+                         TargetAddress,
+                         TransferSize);
+       }
       else
-      {
-         IDEWriteBlock(DeviceExtension->CommandPortBase,
-                      TargetAddress,
-                      TransferSize);
-      }
+       {
+         IDEWriteBlock(DeviceExtension->CommandPortBase,
+                       TargetAddress,
+                       TransferSize);
+       }
     }
 
   DPRINT("AtapiReadWrite() done!\n");
@@ -2262,7 +2274,7 @@ AtapiFlushCache(PATAPI_MINIPORT_EXTENSION DeviceExtension,
       return(SRB_STATUS_INVALID_LUN);
     }
 
-  if (DeviceExtension->DevicePresent[Srb->TargetId] == FALSE)
+  if (!(DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_PRESENT))
     {
       Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
       return(SRB_STATUS_NO_DEVICE);
@@ -2323,6 +2335,116 @@ AtapiFlushCache(PATAPI_MINIPORT_EXTENSION DeviceExtension,
 }
 
 
+static ULONG
+AtapiTestUnitReady(PATAPI_MINIPORT_EXTENSION DeviceExtension,
+                  PSCSI_REQUEST_BLOCK Srb)
+{
+  ULONG Retries;
+  UCHAR Status;
+  UCHAR Error;
+
+  DPRINT1("AtapiTestUnitReady() called!\n");
+
+  if (Srb->PathId != 0)
+    {
+      Srb->SrbStatus = SRB_STATUS_INVALID_PATH_ID;
+      return(SRB_STATUS_INVALID_PATH_ID);
+    }
+
+  if (Srb->TargetId > 1)
+    {
+      Srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID;
+      return(SRB_STATUS_INVALID_TARGET_ID);
+    }
+
+  if (Srb->Lun != 0)
+    {
+      Srb->SrbStatus = SRB_STATUS_INVALID_LUN;
+      return(SRB_STATUS_INVALID_LUN);
+    }
+
+  if (!(DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_PRESENT))
+    {
+      Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
+      return(SRB_STATUS_NO_DEVICE);
+    }
+
+  DPRINT1("SCSIOP_TEST_UNIT_READY: TargetId: %lu\n",
+        Srb->TargetId);
+
+  /* Return success if media status is not supported */
+  if (!(DeviceExtension->DeviceFlags[Srb->TargetId] & DEVICE_MEDIA_STATUS))
+    {
+      Srb->SrbStatus = SRB_STATUS_SUCCESS;
+      return(SRB_STATUS_SUCCESS);
+    }
+
+  /* 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);
+    }
+  DPRINT1("Status=%02x\n", Status);
+  DPRINT1("Waited %ld usecs for busy to clear\n", Retries * 10);
+  if (Retries >= IDE_MAX_BUSY_RETRIES)
+    {
+      DPRINT1("Drive is BUSY for too long\n");
+      return(SRB_STATUS_BUSY);
+    }
+
+  /* Select the desired drive */
+  IDEWriteDriveHead(DeviceExtension->CommandPortBase,
+                   IDE_DH_FIXED | (Srb->TargetId ? IDE_DH_DRV1 : 0));
+  ScsiPortStallExecution(10);
+
+  /* Issue command to drive */
+  IDEWriteCommand(DeviceExtension->CommandPortBase, IDE_CMD_GET_MEDIA_STATUS);
+
+  /* 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;
+       }
+      KeStallExecutionProcessor(10);
+    }
+  if (Retries >= IDE_MAX_WRITE_RETRIES)
+    {
+      DPRINT1("Drive is BUSY for too long after sending write command\n");
+      return(SRB_STATUS_BUSY);
+    }
+
+  if (Status & IDE_SR_ERR)
+    {
+      Error = IDEReadError(DeviceExtension->CommandPortBase);
+      if (Error == IDE_ER_UNC)
+       {
+         /* Handle write protection 'error' */
+         Srb->SrbStatus = SRB_STATUS_SUCCESS;
+         return(SRB_STATUS_SUCCESS);
+       }
+      else
+       {
+         /* Indicate expecting an interrupt. */
+         DeviceExtension->ExpectingInterrupt = TRUE;
+         return(SRB_STATUS_PENDING);
+       }
+    }
+
+  DPRINT1("AtapiTestUnitReady() done!\n");
+
+  Srb->SrbStatus = SRB_STATUS_SUCCESS;
+  return(SRB_STATUS_SUCCESS);
+}
+
+
 static UCHAR
 AtapiErrorToScsi(PVOID DeviceExtension,
                 PSCSI_REQUEST_BLOCK Srb)
@@ -2343,7 +2465,7 @@ AtapiErrorToScsi(PVOID DeviceExtension,
 
   ErrorReg = IDEReadError(CommandPortBase);
 
-  if (DevExt->DeviceAtapi[Srb->TargetId])
+  if (DevExt->DeviceFlags[Srb->TargetId] & DEVICE_ATAPI)
     {
       switch (ErrorReg >> 4)
        {
index 6688b4c..09da13c 100644 (file)
@@ -75,6 +75,7 @@ extern "C" {
 #define    IDE_CMD_FLUSH_CACHE_EXT  0xEA
 #define    IDE_CMD_IDENT_ATA_DRV    0xEC
 #define    IDE_CMD_IDENT_ATAPI_DRV  0xA1
+#define    IDE_CMD_GET_MEDIA_STATUS 0xDA
 
 //
 //  Access macros for command registers
@@ -179,7 +180,25 @@ typedef struct _IDE_DRIVE_IDENTIFY
   WORD  RWMultCurrent;       /*59*/
   WORD  TMSectorCountLo;     /*60*/
   WORD  TMSectorCountHi;     /*61*/
-  WORD  Reserved62[193];     /*62*/
+  WORD  DmaModes;            /*62*/
+  WORD  MultiDmaModes;       /*63*/
+  WORD  Reserved64[5];       /*64*/
+  WORD  Reserved69[2];       /*69*/
+  WORD  Reserved71[4];       /*71*/
+  WORD  MaxQueueDepth;       /*75*/
+  WORD  Reserved76[4];       /*79*/
+  WORD  MajorRevision;       /*80*/
+  WORD  MinorRevision;       /*81*/
+  WORD  SupportedFeatures82; /*82*/
+  WORD  SupportedFeatures83; /*83*/
+  WORD  SupportedFeatures84; /*84*/
+  WORD  EnabledFeatures85;   /*85*/
+  WORD  EnabledFeatures86;   /*86*/
+  WORD  EnabledFeatures87;   /*87*/
+  WORD  UltraDmaModes;       /*88*/
+  WORD  Reserved89[11];      /*89*/
+  WORD  Max48BitAddress[4];  /*100*/
+  WORD  Reserved104[151];    /*104*/
   WORD  Checksum;            /*255*/
 } IDE_DRIVE_IDENTIFY, *PIDE_DRIVE_IDENTIFY;