Implemented ATAPI support.
authorEric Kohl <eric.kohl@reactos.org>
Tue, 19 Mar 2002 00:48:52 +0000 (00:48 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Tue, 19 Mar 2002 00:48:52 +0000 (00:48 +0000)
svn path=/trunk/; revision=2739

reactos/drivers/storage/atapi/atapi.c

index 6b1ff08..280b1e8 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.13 2002/03/16 16:13:57 ekohl Exp $
+/* $Id: atapi.c,v 1.14 2002/03/19 00:48:52 ekohl Exp $
  *
  * COPYRIGHT:   See COPYING in the top level directory
  * PROJECT:     ReactOS ATAPI miniport driver
@@ -480,7 +480,7 @@ AtapiFindIsaBusController(PVOID DeviceExtension,
   BOOLEAN ChannelFound = FALSE;
   BOOLEAN DeviceFound = FALSE;
 
-  DPRINT1("AtapiFindIsaBusController() called!\n");
+  DPRINT("AtapiFindIsaBusController() called!\n");
 
   *Again = FALSE;
 
@@ -538,7 +538,7 @@ AtapiFindIsaBusController(PVOID DeviceExtension,
     }
   else
     {
-      DPRINT1("AtapiFindIsaBusController() both channels claimed. Returns: SP_RETURN_NOT_FOUND\n");
+      DPRINT("AtapiFindIsaBusController() both channels claimed. Returns: SP_RETURN_NOT_FOUND\n");
       *Again = FALSE;
       return(SP_RETURN_NOT_FOUND);
     }
@@ -550,7 +550,7 @@ AtapiFindIsaBusController(PVOID DeviceExtension,
                                     ConfigInfo);
     }
 
-  DPRINT1("AtapiFindIsaBusController() returns: SP_RETURN_FOUND\n");
+  DPRINT("AtapiFindIsaBusController() returns: SP_RETURN_FOUND\n");
   return(SP_RETURN_FOUND);
 }
 
@@ -655,11 +655,11 @@ AtapiInterrupt(IN PVOID DeviceExtension)
 
   UCHAR DeviceStatus;
   BOOLEAN IsLastBlock;
+  BOOLEAN IsAtapi;
   ULONG Retries;
-  NTSTATUS ErrorStatus;
-  ULONG ErrorInformation;
   PUCHAR TargetAddress;
   ULONG SectorSize;
+  ULONG TransferSize;
 
 
   DPRINT("AtapiInterrupt() called!\n");
@@ -667,21 +667,21 @@ AtapiInterrupt(IN PVOID DeviceExtension)
   DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension;
   if (DevExt->ExpectingInterrupt == FALSE)
     {
+      DPRINT1("AtapiInterrupt(): Unexpected interrupt\n");
       return(FALSE);
     }
 
   Srb = DevExt->CurrentSrb;
-
   DPRINT("Srb: %p\n", Srb);
 
   CommandPortBase = DevExt->CommandPortBase;
   ControlPortBase = DevExt->ControlPortBase;
-
   DPRINT("CommandPortBase: %lx  ControlPortBase: %lx\n", CommandPortBase, ControlPortBase);
 
+  IsAtapi = DevExt->DeviceAtapi[Srb->TargetId];
+  DPRINT("IsAtapi == %s\n", (IsAtapi) ? "TRUE" : "FALSE");
+
   IsLastBlock = FALSE;
-  ErrorStatus = STATUS_SUCCESS;
-  ErrorInformation = 0;
 
   DeviceStatus = IDEReadStatus(CommandPortBase);
 
@@ -699,114 +699,131 @@ AtapiInterrupt(IN PVOID DeviceExtension)
       SectorCount = IDEReadSectorCount(CommandPortBase);
       SectorNum = IDEReadSectorNum(CommandPortBase);
 
-      /* FIXME: should use the NT error logging facility */
-      DbgPrint("ATAPI Error: OP:%02x STAT:%02x ERR:%02x CYLLO:%02x CYLHI:%02x SCNT:%02x SNUM:%02x\n",
-              0, //DeviceExtension->Operation,
-              DeviceStatus,
-              ErrorReg,
-              CylinderLow,
-              CylinderHigh,
-              SectorCount,
-              SectorNum);
-
-      /* FIXME: should retry the command and perhaps recalibrate the drive */
-
-        //  Set error status information
-      ErrorStatus = STATUS_DISK_OPERATION_FAILED;
-#if 0
-      ErrorInformation = 
-          (((((((CylinderHigh << 8) + CylinderLow) * 
-              DeviceExtension->LogicalHeads) + 
-              (DriveHead % DeviceExtension->LogicalHeads)) * 
-              DeviceExtension->SectorsPerLogTrk) + SectorNum - 1) -
-          DeviceExtension->StartingSector) * DeviceExtension->BytesPerSector;
-#endif
+      DPRINT1("ATAPI Error: STAT:%02x ERR:%02x CYLLO:%02x CYLHI:%02x SCNT:%02x SNUM:%02x\n",
+             DeviceStatus,
+             ErrorReg,
+             CylinderLow,
+             CylinderHigh,
+             SectorCount,
+             SectorNum);
+
+      /* FIXME: set a useful status code */
+      Srb->SrbStatus = SRB_STATUS_ERROR;
+      IsLastBlock = TRUE;
     }
   else
     {
-      switch (Srb->Cdb[0])
+      if (Srb->SrbFlags & SRB_FLAGS_DATA_IN)
        {
-         case SCSIOP_READ:
-           DPRINT("SCSIOP_READ\n");
-
-           /* Update controller/device state variables */
-           SectorSize = DevExt->DeviceParams[Srb->TargetId].BytesPerSector;
-           TargetAddress = Srb->DataBuffer;
-           Srb->DataBuffer += SectorSize;
-           Srb->DataTransferLength -= SectorSize;
-
-           /* Remember whether DRQ should be low at end (last block read) */
-           IsLastBlock = (Srb->DataTransferLength == 0);
-           DPRINT("IsLastBlock == %s\n", (IsLastBlock)?"TRUE":"FALSE");
-
-           /* Wait for DRQ assertion */
-           for (Retries = 0; Retries < IDE_MAX_DRQ_RETRIES &&
-                !(IDEReadStatus(CommandPortBase) & IDE_SR_DRQ);
-                Retries++)
-             {
+         DPRINT("Read data\n");
+
+         /* Update controller/device state variables */
+         TargetAddress = Srb->DataBuffer;
+
+         if (IsAtapi)
+           {
+             TransferSize = IDEReadCylinderLow(CommandPortBase);
+             TransferSize += IDEReadCylinderHigh(CommandPortBase) << 8;
+           }
+         else
+           {
+             TransferSize = DevExt->DeviceParams[Srb->TargetId].BytesPerSector;
+           }
+
+         DPRINT("TransferLength: %lu\n", Srb->DataTransferLength);
+         DPRINT("TransferSize: %lu\n", TransferSize);
+
+         if (Srb->DataTransferLength <= TransferSize)
+           {
+             Srb->DataTransferLength = 0;
+             IsLastBlock = TRUE;
+           }
+         else
+           {
+             Srb->DataTransferLength -= TransferSize;
+             IsLastBlock = FALSE;
+           }
+         Srb->DataBuffer += TransferSize;
+         DPRINT("IsLastBlock == %s\n", (IsLastBlock) ? "TRUE" : "FALSE");
+
+         /* Wait for DRQ assertion */
+         for (Retries = 0; Retries < IDE_MAX_DRQ_RETRIES &&
+              !(IDEReadStatus(CommandPortBase) & IDE_SR_DRQ);
+              Retries++)
+           {
                KeStallExecutionProcessor(10);
-             }
-
-           /* Copy the block of data */
-           IDEReadBlock(CommandPortBase,
-                        TargetAddress,
-                        SectorSize);
-
-           /* check DRQ */
-           if (IsLastBlock)
-             {
-               for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES &&
-                    (IDEReadStatus(CommandPortBase) & IDE_SR_BUSY);
-                    Retries++)
-                 {
-                   KeStallExecutionProcessor(10);
-                 }
-
-               /* Check for data overrun */
-               if (IDEReadStatus(CommandPortBase) & IDE_SR_DRQ)
-                 {
-                   /* FIXME: Handle error! */
-                 }
-             }
-           break;
-
-         case SCSIOP_WRITE:
-           DPRINT("SCSIOP_WRITE\n");
-           if (Srb->DataTransferLength == 0)
-             {
-
-               for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES &&
-                    (IDEReadStatus(CommandPortBase) & IDE_SR_BUSY);
-                    Retries++)
-                 {
-                   KeStallExecutionProcessor(10);
-                 }
-
-               /* Check for data overrun */
-               if (IDEReadStatus(CommandPortBase) & IDE_SR_DRQ)
-                 {
-                   /* FIXME: Handle error! */
-                 }
-
-               DevExt->ExpectingInterrupt = FALSE;
-               IsLastBlock = TRUE;
-             }
-           else
-             {
-               /* Update SRB data */
-               SectorSize = DevExt->DeviceParams[Srb->TargetId].BytesPerSector;
-
-               TargetAddress = Srb->DataBuffer;
-               Srb->DataBuffer += SectorSize;
-               Srb->DataTransferLength -= SectorSize;
-
-               /* Write the sector */
-               IDEWriteBlock(CommandPortBase,
-                             TargetAddress,
-                             SectorSize);
-             }
-           break;
-      }
+           }
+
+         /* Copy the block of data */
+         IDEReadBlock(CommandPortBase,
+                      TargetAddress,
+                      TransferSize);
+
+         /* check DRQ */
+         if (IsLastBlock)
+           {
+             for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES &&
+                  (IDEReadStatus(CommandPortBase) & IDE_SR_BUSY);
+                  Retries++)
+               {
+                 KeStallExecutionProcessor(10);
+               }
+
+             /* Check for data overrun */
+             if (IDEReadStatus(CommandPortBase) & IDE_SR_DRQ)
+               {
+                 /* FIXME: Handle error! */
+               }
+           }
+
+         Srb->SrbStatus = SRB_STATUS_SUCCESS;
+       }
+      else if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)
+       {
+         DPRINT("Write data\n");
+
+         if (Srb->DataTransferLength == 0)
+           {
+
+             for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES &&
+                  (IDEReadStatus(CommandPortBase) & IDE_SR_BUSY);
+                  Retries++)
+               {
+                 KeStallExecutionProcessor(10);
+               }
+
+             /* Check for data overrun */
+             if (IDEReadStatus(CommandPortBase) & IDE_SR_DRQ)
+               {
+                 /* FIXME: Handle error! */
+               }
+
+             DevExt->ExpectingInterrupt = FALSE;
+             IsLastBlock = TRUE;
+           }
+         else
+           {
+             /* Update SRB data */
+             SectorSize = DevExt->DeviceParams[Srb->TargetId].BytesPerSector;
+
+             TargetAddress = Srb->DataBuffer;
+             Srb->DataBuffer += SectorSize;
+             Srb->DataTransferLength -= SectorSize;
+
+             /* Write the sector */
+             IDEWriteBlock(CommandPortBase,
+                           TargetAddress,
+                           SectorSize);
+           }
+
+         Srb->SrbStatus = SRB_STATUS_SUCCESS;
+       }
+      else
+       {
+         DPRINT1("Unspecified transfer direction!\n");
+         Srb->SrbStatus = SRB_STATUS_ERROR;
+         IsLastBlock = TRUE;
+       }
     }
 
   /* complete this packet */
@@ -1311,20 +1328,12 @@ static ULONG
 AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
                      IN PSCSI_REQUEST_BLOCK Srb)
 {
-#if 0
-//  PIDE_DRIVE_IDENTIFY DeviceParams;
-
-//  ULONG StartingSector,i;
-//  ULONG SectorCount;
   UCHAR ByteCountHigh;
   UCHAR ByteCountLow;
-//  UCHAR DrvHead;
-//  UCHAR SectorNumber;
-//  UCHAR Command;
   ULONG Retries;
   UCHAR Status;
 
-  DPRINT1("AtapiSendAtapiCommand() called!\n");
+  DPRINT("AtapiSendAtapiCommand() called!\n");
 
   if ((Srb->PathId != 0) ||
       (Srb->TargetId > 1) ||
@@ -1334,16 +1343,16 @@ AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
       return(SRB_STATUS_SELECTION_TIMEOUT);
     }
 
-  DPRINT1("AtapiSendAtapiCommand(): TargetId: %lu\n",
+  DPRINT("AtapiSendAtapiCommand(): TargetId: %lu\n",
         Srb->TargetId);
 
+  if (Srb->Cdb[0] == SCSIOP_INQUIRY)
+    return(AtapiInquiry(DeviceExtension,
+                       Srb));
 
   /* Set pointer to data buffer. */
   DeviceExtension->DataBuffer = (PUSHORT)Srb->DataBuffer;
-
   DeviceExtension->CurrentSrb = Srb;
-  DeviceExtension->ExpectingInterrupt = TRUE;
-
 
   /*  wait for BUSY to clear  */
   for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
@@ -1359,7 +1368,7 @@ AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
   DPRINT("waited %ld usecs for busy to clear\n", Retries * 10);
   if (Retries >= IDE_MAX_BUSY_RETRIES)
     {
-      DPRINT ("Drive is BUSY for too long\n");
+      DPRINT("Drive is BUSY for too long\n");
       return(SRB_STATUS_BUSY);
 #if 0
       if (++ControllerExtension->Retries > IDE_MAX_CMD_RETRIES)
@@ -1420,18 +1429,18 @@ AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
 #endif
     }
 
-  ByteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF);
-  ByteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8);
+  ByteCountLow = 12;
+  ByteCountHigh = 0;
 
+  /* Set command packet length */
   IDEWriteCylinderHigh(DeviceExtension->CommandPortBase, ByteCountHigh);
   IDEWriteCylinderLow(DeviceExtension->CommandPortBase, ByteCountLow);
-//  IDEWriteDriveHead(DeviceExtension->CommandPortBase, IDE_DH_FIXED | DrvHead);
 
   /* Issue command to drive */
   IDEWriteCommand(DeviceExtension->CommandPortBase, 0xA0); /* Packet command */
 
 
-  /*  wait for DRQ to assert */
+  /* Wait for DRQ to assert */
   for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
     {
       Status = IDEReadStatus(DeviceExtension->CommandPortBase);
@@ -1442,73 +1451,16 @@ AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
       ScsiPortStallExecution(10);
     }
 
+  /* Write command packet */
   IDEWriteBlock(DeviceExtension->CommandPortBase,
                (PUSHORT)Srb->Cdb,
                12);
 
+  DeviceExtension->ExpectingInterrupt = TRUE;
 
-  DPRINT1("AtapiSendAtapiCommand() done\n");
-  return(SRB_STATUS_PENDING);
-#endif
-
-//#if 0
-  ULONG SrbStatus = SRB_STATUS_SELECTION_TIMEOUT;
-
-  DPRINT("AtapiSendAtapiCommand() called!\n");
-
-  switch (Srb->Cdb[0])
-    {
-      case SCSIOP_INQUIRY:
-       DPRINT("  SCSIOP_INQUIRY\n");
-       SrbStatus = AtapiInquiry(DeviceExtension,
-                                Srb);
-       break;
-
-      case SCSIOP_READ_CAPACITY:
-       DPRINT1("  SCSIOP_READ_CAPACITY\n");
-       break;
-
-      case SCSIOP_READ:
-       DPRINT1("  SCSIOP_READ\n");
-       break;
-
-      case SCSIOP_WRITE:
-       DPRINT1("  SCSIOP_WRITE\n");
-       break;
-
-      case SCSIOP_MODE_SENSE:
-       DPRINT1("  SCSIOP_MODE_SENSE\n");
-       break;
-
-      case SCSIOP_TEST_UNIT_READY:
-       DPRINT1("  SCSIOP_TEST_UNIT_READY\n");
-       break;
-
-      case SCSIOP_VERIFY:
-       DPRINT1("  SCSIOP_VERIFY\n");
-       break;
-
-      case SCSIOP_START_STOP_UNIT:
-       DPRINT1("  SCSIOP_START_STOP_UNIT\n");
-       break;
-
-      case SCSIOP_REQUEST_SENSE:
-       DPRINT1("  SCSIOP_REQUEST_SENSE\n");
-       break;
-
-     default:
-       DbgPrint("AtapiSendIdeCommand():unknown command %x\n",
-                Srb->Cdb[0]);
-       break;
-    }
-
-  if (SrbStatus == SRB_STATUS_SELECTION_TIMEOUT)
-    {
-      DPRINT1("Not implemented yet!\n");
-    }
+  DPRINT("AtapiSendAtapiCommand() done\n");
 
-  return(SrbStatus);
-//#endif
+  return(SRB_STATUS_PENDING);
 }
 
 
@@ -1571,7 +1523,8 @@ AtapiInquiry(PATAPI_MINIPORT_EXTENSION DeviceExtension,
   PINQUIRYDATA InquiryData;
   ULONG i;
 
-  DPRINT("SCSIOP_INQUIRY: TargetId: %lu\n", Srb->TargetId);
+  DPRINT1("SCSIOP_INQUIRY: DeviceExtension %p  TargetId: %lu\n",
+         DeviceExtension, Srb->TargetId);
 
   if ((Srb->PathId != 0) ||
       (Srb->TargetId > 1) ||
@@ -1631,6 +1584,8 @@ AtapiInquiry(PATAPI_MINIPORT_EXTENSION DeviceExtension,
        ((PUCHAR)DeviceParams->FirmwareRev)[i+1];
     }
 
+  DPRINT1("VendorId: '%.20s'\n", InquiryData->VendorId);
+
   return(SRB_STATUS_SUCCESS);
 }
 
@@ -1871,14 +1826,6 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
 #endif
     }
 
-#if 0
-  if (Command == IDE_CMD_WRITE)
-    {
-      DPRINT1("Write not implemented yet!\n");
-      return(SRB_STATUS_SUCCESS);
-    }
-#endif
-
   /* Indicate expecting an interrupt. */
   DeviceExtension->ExpectingInterrupt = TRUE;