⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xboxdisk.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
        }
      StallExecutionProcessor(10);
    }
  DbgPrint((DPRINT_DISK, "status=0x%x\n", Status));
  DbgPrint((DPRINT_DISK, "waited %d usecs for busy to clear\n", RetryCount * 10));
  if (RetryCount >= IDE_MAX_BUSY_RETRIES)
    {
      DbgPrint((DPRINT_DISK, "Drive is BUSY for too long\n"));
      return FALSE;
    }

  /*  Write Drive/Head to select drive  */
  IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead);
  StallExecutionProcessor(500);

  /* Disable interrupts */
  IDEWriteDriveControl(ControlPort, IDE_DC_nIEN);
  StallExecutionProcessor(500);

  /*  Issue command to drive  */
  if (DrvHead & IDE_DH_LBA)
    {
      DbgPrint((DPRINT_DISK, "READ:DRV=%d:LBA=1:BLK=%d:SC=0x%x:CM=0x%x\n",
                DrvHead & IDE_DH_DRV1 ? 1 : 0,
                ((DrvHead & 0x0f) << 24) + (CylinderHigh << 16) + (CylinderLow << 8) + SectorNum,
                SectorCnt,
                Command));
    }
  else
    {
      DbgPrint((DPRINT_DISK, "READ:DRV=%d:LBA=0:CH=0x%x:CL=0x%x:HD=0x%x:SN=0x%x:SC=0x%x:CM=0x%x\n",
                DrvHead & IDE_DH_DRV1 ? 1 : 0,
                CylinderHigh,
                CylinderLow,
                DrvHead & 0x0f,
                SectorNum,
                SectorCnt,
                Command));
    }

  /*  Setup command parameters  */
  IDEWritePrecomp(CommandPort, PreComp);
  IDEWriteSectorCount(CommandPort, SectorCnt);
  IDEWriteSectorNum(CommandPort, SectorNum);
  IDEWriteCylinderHigh(CommandPort, CylinderHigh);
  IDEWriteCylinderLow(CommandPort, CylinderLow);
  IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead);

  /*  Issue the command  */
  IDEWriteCommand(CommandPort, Command);
  StallExecutionProcessor(50);

  /*  wait for DRQ or error  */
  for (RetryCount = 0; RetryCount < IDE_MAX_POLL_RETRIES; RetryCount++)
    {
      Status = IDEReadStatus(CommandPort);
      if (!(Status & IDE_SR_BUSY))
	{
	  if (Status & IDE_SR_ERR)
	    {
	      IDEWriteDriveControl(ControlPort, 0);
	      StallExecutionProcessor(50);
	      IDEReadStatus(CommandPort);

	      return FALSE;
	    }

	  if (Status & IDE_SR_DRQ)
	    {
	      break;
	    }
	  else
	    {
	      IDEWriteDriveControl(ControlPort, 0);
	      StallExecutionProcessor(50);
	      IDEReadStatus(CommandPort);

	      return FALSE;
	    }
	}
      StallExecutionProcessor(10);
    }

  /*  timed out  */
  if (RetryCount >= IDE_MAX_POLL_RETRIES)
    {
      IDEWriteDriveControl(ControlPort, 0);
      StallExecutionProcessor(50);
      IDEReadStatus(CommandPort);

      return FALSE;
    }

  while (1)
    {
      /*  Read data into buffer  */
      if (Junk == FALSE)
	{
	  IDEReadBlock(CommandPort, Buffer, IDE_SECTOR_BUF_SZ);
	  Buffer = (PVOID)((ULONG_PTR)Buffer + IDE_SECTOR_BUF_SZ);
	}
      else
	{
	  UCHAR JunkBuffer[IDE_SECTOR_BUF_SZ];
	  IDEReadBlock(CommandPort, JunkBuffer, IDE_SECTOR_BUF_SZ);
	}
      SectorCount++;

      /*  Check for error or more sectors to read  */
      for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
	{
	  Status = IDEReadStatus(CommandPort);
	  if (!(Status & IDE_SR_BUSY))
	    {
	      if (Status & IDE_SR_ERR)
		{
		  IDEWriteDriveControl(ControlPort, 0);
		  StallExecutionProcessor(50);
		  IDEReadStatus(CommandPort);

		  return FALSE;
		}
	      if (Status & IDE_SR_DRQ)
		{
		  if (SectorCount >= SectorCnt)
		    {
		      DbgPrint((DPRINT_DISK, "Buffer size exceeded!\n"));
		      Junk = TRUE;
		    }
		  break;
		}
	      else
		{
		  if (SectorCount > SectorCnt)
		    {
		      DbgPrint((DPRINT_DISK, "Read %lu sectors of junk!\n",
                                SectorCount - SectorCnt));
		    }
		  IDEWriteDriveControl(ControlPort, 0);
		  StallExecutionProcessor(50);
		  IDEReadStatus(CommandPort);

		  return TRUE;
		}
	    }
	}
    }
}

BOOLEAN
XboxDiskReadLogicalSectors(ULONG DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
{
  ULONG StartSector;
  UCHAR Count;

  if (DriveNumber < 0x80 || 2 <= (DriveNumber & 0x0f))
    {
      /* Xbox has only 1 IDE controller and no floppy */
      DbgPrint((DPRINT_DISK, "Invalid drive number\n"));
      return FALSE;
    }

  if (UINT64_C(0) != ((SectorNumber + SectorCount) & UINT64_C(0xfffffffff0000000)))
    {
      DbgPrint((DPRINT_DISK, "48bit LBA required but not implemented\n"));
      return FALSE;
    }

  StartSector = (ULONG) SectorNumber;
  while (0 < SectorCount)
    {
      Count = (SectorCount <= 255 ? SectorCount : 255);
      if (! XboxDiskPolledRead(XBOX_IDE_COMMAND_PORT,
                               XBOX_IDE_CONTROL_PORT,
                               0, Count,
                               StartSector & 0xff,
                               (StartSector >> 8) & 0xff,
                               (StartSector >> 16) & 0xff,
                               ((StartSector >> 24) & 0x0f) | IDE_DH_LBA |
                               (0 == (DriveNumber & 0x0f) ? IDE_DH_DRV0 : IDE_DH_DRV1),
                               IDE_CMD_READ,
                                Buffer))
        {
          return FALSE;
        }
      SectorCount -= Count;
      Buffer = (PVOID) ((PCHAR) Buffer + Count * IDE_SECTOR_BUF_SZ);
    }

  return TRUE;
}

BOOLEAN
XboxDiskGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry)
{
  UCHAR SectorData[IDE_SECTOR_BUF_SZ];

  /* This is the Xbox, chances are that there is a Xbox-standard partitionless
   * disk in it so let's check that first */

  if (1 <= PartitionNumber && PartitionNumber <= sizeof(XboxPartitions) / sizeof(XboxPartitions[0]) &&
      MachDiskReadLogicalSectors(DriveNumber, XBOX_SIGNATURE_SECTOR, 1, SectorData))
    {
      if (*((PULONG) SectorData) == XBOX_SIGNATURE)
        {
          memset(PartitionTableEntry, 0, sizeof(PARTITION_TABLE_ENTRY));
          PartitionTableEntry->SystemIndicator = XboxPartitions[PartitionNumber - 1].SystemIndicator;
          PartitionTableEntry->SectorCountBeforePartition = XboxPartitions[PartitionNumber - 1].SectorCountBeforePartition;
          PartitionTableEntry->PartitionSectorCount = XboxPartitions[PartitionNumber - 1].PartitionSectorCount;
          return TRUE;
        }
    }

  /* No magic Xbox partitions. Maybe there's a MBR */
  return DiskGetPartitionEntry(DriveNumber, PartitionNumber, PartitionTableEntry);
}

BOOLEAN
XboxDiskGetDriveGeometry(ULONG DriveNumber, PGEOMETRY Geometry)
{
  IDE_DRIVE_IDENTIFY DrvParms;
  ULONG i;
  BOOLEAN Atapi;

  Atapi = FALSE; /* FIXME */
  /*  Get the Drive Identify block from drive or die  */
  if (! XboxDiskPolledRead(XBOX_IDE_COMMAND_PORT,
                           XBOX_IDE_CONTROL_PORT,
                           0,
                           1,
                           0,
                           0,
                           0,
                           (0 == (DriveNumber & 0x0f) ? IDE_DH_DRV0 : IDE_DH_DRV1),
                           (Atapi ? IDE_CMD_IDENT_ATAPI_DRV : IDE_CMD_IDENT_ATA_DRV),
                           (PUCHAR) &DrvParms))
    {
      DbgPrint((DPRINT_DISK, "XboxDiskPolledRead() failed\n"));
      return FALSE;
    }

  Geometry->Cylinders = DrvParms.LogicalCyls;
  Geometry->Heads = DrvParms.LogicalHeads;
  Geometry->Sectors = DrvParms.SectorsPerTrack;

  if (! Atapi && 0 != (DrvParms.Capabilities & IDE_DRID_LBA_SUPPORTED))
    {
      /* LBA ATA drives always have a sector size of 512 */
      Geometry->BytesPerSector = 512;
    }
  else
    {
      DbgPrint((DPRINT_DISK, "BytesPerSector %d\n", DrvParms.BytesPerSector));
      if (DrvParms.BytesPerSector == 0)
        {
          Geometry->BytesPerSector = 512;
        }
      else
        {
          for (i = 15; i >= 0; i--)
            {
              if (0 != (DrvParms.BytesPerSector & (1 << i)))
                {
                  Geometry->BytesPerSector = 1 << i;
                  break;
                }
            }
        }
    }
  DbgPrint((DPRINT_DISK, "Cylinders %d\n", Geometry->Cylinders));
  DbgPrint((DPRINT_DISK, "Heads %d\n", Geometry->Heads));
  DbgPrint((DPRINT_DISK, "Sectors %d\n", Geometry->Sectors));
  DbgPrint((DPRINT_DISK, "BytesPerSector %d\n", Geometry->BytesPerSector));

  return TRUE;
}

ULONG
XboxDiskGetCacheableBlockCount(ULONG DriveNumber)
{
  /* 64 seems a nice number, it is used by the machpc code for LBA devices */
  return 64;
}

/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -