[ros-kernel] Removable Media Support is Broken.

James Tabor jimtabor at adsl-64-217-116-74.dsl.hstntx.swbell.net
Wed Jul 14 07:09:04 CEST 2004


Hi!
Hartmut Birr wrote:
> 
> Hi,
> 
> I think this is a problem of DriveNotReady. Did you try to disable the
> DriveNotReady check in DiskClassCheckReadWrite? The problem is, it exist
> DriveNotReady for Partition0 and Partition1. If is no disk in the drive at
> boot time, DriveNotReady for Partition0 is set. This value is never changed
> again. DiskClassCheckReadWrite fails always, if the partition table is read
> from Partition0.
> 
> - Hartmut  
> 
Ok, I think I found the right answer.

 From "Inside Microsoft Windows 2000" Pages 619 to 621.

Disk class driver creates the link \Device\Harddisk0\Partition0 to refer to
\Device\Harddisk0\DR0, and \Device\Harddisk0\Partition1 to refer to the
first partition device object of the first disk.

Doh! I know exactly what you are writing about and what you are trying to do.

So here is my hack, (sorry it's not a patch):

static NTSTATUS
DiskBuildPartitionTable(IN PDEVICE_OBJECT DiskDeviceObject,
                         IN PIRP Irp)
{
   PDRIVE_LAYOUT_INFORMATION PartitionList = NULL;
   PDEVICE_EXTENSION DiskDeviceExtension, DDE;
   PDISK_DATA DiskData, DD;
   PPARTITION_INFORMATION PartitionEntry;
   ULONG PartitionNumber;
   NTSTATUS Status;

   DPRINT("DiskBuildPartitionTable() start\n");

   DiskDeviceExtension = (PDEVICE_EXTENSION)DiskDeviceObject->DeviceExtension;
   DiskData = (PDISK_DATA)(DiskDeviceExtension + 1);

/*
	We have to move down the device object tree to get the flag we want to
	clear.
  */
   DDE = (PDEVICE_EXTENSION) DiskDeviceExtension->PhysicalDevice->DeviceExtension;
   DD = (PDISK_DATA)(DDE +1);

/* clear the flag and move on to the next problem */

   DD->DriveNotReady = FALSE;

   Status = ScsiClassReadDriveCapacity(DiskDeviceObject);
   if (!NT_SUCCESS(Status))
     {
       /* Drive is not ready. */
       DPRINT("Drive not ready\n");
       DiskData->DriveNotReady = TRUE;
       return Status;
     }

/*

	Don't need this anymore!

    A previous partition table may exist for this Device Object.
    We will need to delete this data and force a rebuild.
  */
//  if(DiskDeviceExtension->StartingOffset.QuadPart)
//  {
//     DPRINT("Partition already installed!\n");
//     DiskData->PartitionType = 0;
//     DiskData->PartitionNumber = 0;
//     DiskData->PartitionOrdinal = 0;
//     DiskData->HiddenSectors = 0;
//     DiskData->BootIndicator = 0;
//     DiskData->DriveNotReady = FALSE;
//     DiskDeviceExtension->StartingOffset.QuadPart = 0;
//     DiskDeviceExtension->PartitionLength.QuadPart = 0;
//  }

   /* Read partition table */
   Status = IoReadPartitionTable(DiskDeviceExtension->PhysicalDevice,
//  Status = IoReadPartitionTable(DiskDeviceObject,
				DiskDeviceExtension->DiskGeometry->BytesPerSector,
				TRUE,
				&PartitionList);

   DPRINT("IoReadPartitionTable(): Status: %lx\n", Status);

   if (!NT_SUCCESS(Status))
     {
       /* Drive is not ready. */
       DPRINT("Drive not ready\n");
       DiskData->DriveNotReady = TRUE;
       if (PartitionList != NULL)
           ExFreePool(PartitionList);
       return Status;
     }

   if (NT_SUCCESS(Status))
     {
       DPRINT("Read partition table!\n");
       DPRINT("  Number of partitions: %u\n", PartitionList->PartitionCount);

       /* Set disk signature */
       DiskData->Signature = PartitionList->Signature;

       DiskData->NextPartition = NULL;

       if (PartitionList->PartitionCount)
         {
           for (PartitionNumber = 0; PartitionNumber < PartitionList->PartitionCount; PartitionNumber++)
	    {
	      PartitionEntry = &PartitionList->PartitionEntry[PartitionNumber];

       	      DiskData->PartitionType = PartitionEntry->PartitionType;
       	      DiskData->PartitionNumber = PartitionNumber + 1;
       	      DiskData->PartitionOrdinal = PartitionNumber + 1;
       	      DiskData->HiddenSectors = PartitionEntry->HiddenSectors;
       	      DiskData->BootIndicator = PartitionEntry->BootIndicator;
       	      DiskData->DriveNotReady = FALSE;
       	      DiskDeviceExtension->StartingOffset = PartitionEntry->StartingOffset;
       	      DiskDeviceExtension->PartitionLength = PartitionEntry->PartitionLength;
		
	      DPRINT1("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n",
		      PartitionNumber,
		      DiskData->PartitionNumber,
		      DiskData->BootIndicator,
		      DiskData->PartitionType,
		      DiskDeviceExtension->StartingOffset.QuadPart / 512 /*DrvParms.BytesPerSector*/,
		      DiskDeviceExtension->PartitionLength.QuadPart / 512 /* DrvParms.BytesPerSector*/);
	    }
	}
       else
         {
	  DiskData->PartitionType = 0;
	  DiskData->PartitionNumber = 1;
	  DiskData->PartitionOrdinal = 0;
	  DiskData->HiddenSectors = 0;
	  DiskData->BootIndicator = 0;
	  DiskData->DriveNotReady = FALSE;
	  DiskDeviceExtension->StartingOffset.QuadPart = 0;
	  DiskDeviceExtension->PartitionLength.QuadPart += DiskDeviceExtension->StartingOffset.QuadPart;
	}
     }

   DPRINT("DiskBuildPartitionTable() done\n");
   if (PartitionList != NULL)
        ExFreePool(PartitionList);
   return(STATUS_SUCCESS);
}


Now it work like you want it to! Inside M$ Win 2k had me confused, sorry about
that!

Thanks for hitting me on the head! ;^)
James

ps. I'll commit changes after your comments.



More information about the Ros-kernel mailing list