ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

xboxhw.c
Go to the documentation of this file.
00001 /* $Id: xboxhw.c 56270 2012-03-29 08:25:20Z tkreuzer $
00002  *
00003  *  FreeLoader
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License along
00016  *  with this program; if not, write to the Free Software Foundation, Inc.,
00017  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00018  */
00019 
00020 #include <freeldr.h>
00021 
00022 #define NDEBUG
00023 #include <debug.h>
00024 
00025 DBG_DEFAULT_CHANNEL(HWDETECT);
00026 
00027 static CHAR Hex[] = "0123456789ABCDEF";
00028 //static unsigned int delay_count = 1;
00029 
00030 extern ULONG reactos_disk_count;
00031 extern ARC_DISK_SIGNATURE reactos_arc_disk_info[];
00032 extern char reactos_arc_strings[32][256];
00033 
00034 static PCM_PARTIAL_RESOURCE_LIST
00035 GetHarddiskConfigurationData(UCHAR DriveNumber, ULONG* pSize)
00036 {
00037   PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
00038   PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
00039   //EXTENDED_GEOMETRY ExtGeometry;
00040   GEOMETRY Geometry;
00041   ULONG Size;
00042 
00043     //
00044     // Initialize returned size
00045     //
00046     *pSize = 0;
00047 
00048   /* Set 'Configuration Data' value */
00049   Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
00050      sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
00051   PartialResourceList = MmHeapAlloc(Size);
00052   if (PartialResourceList == NULL)
00053     {
00054       ERR("Failed to allocate a full resource descriptor\n");
00055       return NULL;
00056     }
00057 
00058   memset(PartialResourceList, 0, Size);
00059   PartialResourceList->Version = 1;
00060   PartialResourceList->Revision = 1;
00061   PartialResourceList->Count = 1;
00062   PartialResourceList->PartialDescriptors[0].Type =
00063     CmResourceTypeDeviceSpecific;
00064 //  PartialResourceList->PartialDescriptors[0].ShareDisposition =
00065 //  PartialResourceList->PartialDescriptors[0].Flags =
00066   PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
00067     sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
00068 
00069   /* Get pointer to geometry data */
00070   DiskGeometry = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
00071 
00072   /* Get the disk geometry */
00073   //ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);
00074 
00075   if(MachDiskGetDriveGeometry(DriveNumber, &Geometry))
00076     {
00077       DiskGeometry->BytesPerSector = Geometry.BytesPerSector;
00078       DiskGeometry->NumberOfCylinders = Geometry.Cylinders;
00079       DiskGeometry->SectorsPerTrack = Geometry.Sectors;
00080       DiskGeometry->NumberOfHeads = Geometry.Heads;
00081     }
00082   else
00083     {
00084       ERR("Reading disk geometry failed\n");
00085       MmHeapFree(PartialResourceList);
00086       return NULL;
00087     }
00088   TRACE("Disk %x: %u Cylinders  %u Heads  %u Sectors  %u Bytes\n",
00089         DriveNumber,
00090         DiskGeometry->NumberOfCylinders,
00091         DiskGeometry->NumberOfHeads,
00092         DiskGeometry->SectorsPerTrack,
00093         DiskGeometry->BytesPerSector);
00094 
00095     //
00096     // Return configuration data
00097     //
00098     *pSize = Size;
00099     return PartialResourceList;
00100 }
00101 
00102 typedef struct tagDISKCONTEXT
00103 {
00104     UCHAR DriveNumber;
00105     ULONG SectorSize;
00106     ULONGLONG SectorOffset;
00107     ULONGLONG SectorCount;
00108     ULONGLONG SectorNumber;
00109 } DISKCONTEXT;
00110 
00111 static LONG DiskClose(ULONG FileId)
00112 {
00113     DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
00114 
00115     MmHeapFree(Context);
00116     return ESUCCESS;
00117 }
00118 
00119 static LONG DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
00120 {
00121     DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
00122 
00123     RtlZeroMemory(Information, sizeof(FILEINFORMATION));
00124     Information->EndingAddress.QuadPart = (Context->SectorOffset + Context->SectorCount) * Context->SectorSize;
00125     Information->CurrentAddress.QuadPart = (Context->SectorOffset + Context->SectorNumber) * Context->SectorSize;
00126 
00127     return ESUCCESS;
00128 }
00129 
00130 static LONG DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
00131 {
00132     DISKCONTEXT* Context;
00133     ULONG DrivePartition, SectorSize;
00134     UCHAR DriveNumber;
00135     ULONGLONG SectorOffset = 0;
00136     ULONGLONG SectorCount = 0;
00137     PARTITION_TABLE_ENTRY PartitionTableEntry;
00138     CHAR FileName[1];
00139 
00140     if (!DissectArcPath(Path, FileName, &DriveNumber, &DrivePartition))
00141         return EINVAL;
00142 
00143     if (DrivePartition == 0xff)
00144     {
00145         /* This is a CD-ROM device */
00146         SectorSize = 2048;
00147     }
00148     else
00149     {
00150         /* This is either a floppy disk device (DrivePartition == 0) or
00151          * a hard disk device (DrivePartition != 0 && DrivePartition != 0xFF) but
00152          * it doesn't matter which one because they both have 512 bytes per sector */
00153          SectorSize = 512;
00154     }
00155 
00156     if (DrivePartition != 0xff && DrivePartition != 0)
00157     {
00158         if (!XboxDiskGetPartitionEntry(DriveNumber, DrivePartition, &PartitionTableEntry))
00159             return EINVAL;
00160         SectorOffset = PartitionTableEntry.SectorCountBeforePartition;
00161         SectorCount = PartitionTableEntry.PartitionSectorCount;
00162     }
00163     else
00164     {
00165         SectorCount = 0; /* FIXME */
00166     }
00167 
00168     Context = MmHeapAlloc(sizeof(DISKCONTEXT));
00169     if (!Context)
00170         return ENOMEM;
00171     Context->DriveNumber = DriveNumber;
00172     Context->SectorSize = SectorSize;
00173     Context->SectorOffset = SectorOffset;
00174     Context->SectorCount = SectorCount;
00175     Context->SectorNumber = 0;
00176     FsSetDeviceSpecific(*FileId, Context);
00177 
00178     return ESUCCESS;
00179 }
00180 
00181 static LONG DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
00182 {
00183     DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
00184     UCHAR* Ptr = (UCHAR*)Buffer;
00185     ULONG i, Length, Sectors;
00186     BOOLEAN ret;
00187 
00188     *Count = 0;
00189     i = 0;
00190     while (N > 0)
00191     {
00192         Length = N;
00193         if (Length > DISKREADBUFFER_SIZE)
00194             Length = DISKREADBUFFER_SIZE;
00195         Sectors = (Length + Context->SectorSize - 1) / Context->SectorSize;
00196         ret = MachDiskReadLogicalSectors(
00197             Context->DriveNumber,
00198             Context->SectorNumber + Context->SectorOffset + i,
00199             Sectors,
00200             (PVOID)DISKREADBUFFER);
00201         if (!ret)
00202             return EIO;
00203         RtlCopyMemory(Ptr, (PVOID)DISKREADBUFFER, Length);
00204         Ptr += Length;
00205         *Count += Length;
00206         N -= Length;
00207         i += Sectors;
00208     }
00209 
00210     return ESUCCESS;
00211 }
00212 
00213 static LONG DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
00214 {
00215     DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
00216 
00217     if (SeekMode != SeekAbsolute)
00218         return EINVAL;
00219     if (Position->LowPart & (Context->SectorSize - 1))
00220         return EINVAL;
00221 
00222     /* FIXME: take HighPart into account */
00223     Context->SectorNumber = Position->LowPart / Context->SectorSize;
00224     return ESUCCESS;
00225 }
00226 
00227 static const DEVVTBL DiskVtbl = {
00228     DiskClose,
00229     DiskGetFileInformation,
00230     DiskOpen,
00231     DiskRead,
00232     DiskSeek,
00233 };
00234 
00235 static VOID
00236 GetHarddiskIdentifier(PCHAR Identifier,
00237               UCHAR DriveNumber)
00238 {
00239   PMASTER_BOOT_RECORD Mbr;
00240   ULONG *Buffer;
00241   ULONG i;
00242   ULONG Checksum;
00243   ULONG Signature;
00244   CHAR ArcName[256];
00245   PARTITION_TABLE_ENTRY PartitionTableEntry;
00246 
00247   /* Read the MBR */
00248   if (!MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, (PVOID)DISKREADBUFFER))
00249     {
00250       ERR("Reading MBR failed\n");
00251       return;
00252     }
00253 
00254   Buffer = (ULONG*)DISKREADBUFFER;
00255   Mbr = (PMASTER_BOOT_RECORD)DISKREADBUFFER;
00256 
00257   Signature =  Mbr->Signature;
00258   TRACE("Signature: %x\n", Signature);
00259 
00260   /* Calculate the MBR checksum */
00261   Checksum = 0;
00262   for (i = 0; i < 128; i++)
00263     {
00264       Checksum += Buffer[i];
00265     }
00266   Checksum = ~Checksum + 1;
00267   TRACE("Checksum: %x\n", Checksum);
00268 
00269   /* Fill out the ARC disk block */
00270   reactos_arc_disk_info[reactos_disk_count].Signature = Signature;
00271   reactos_arc_disk_info[reactos_disk_count].CheckSum = Checksum;
00272   sprintf(ArcName, "multi(0)disk(0)rdisk(%lu)", reactos_disk_count);
00273   strcpy(reactos_arc_strings[reactos_disk_count], ArcName);
00274   reactos_arc_disk_info[reactos_disk_count].ArcName =
00275       reactos_arc_strings[reactos_disk_count];
00276   reactos_disk_count++;
00277 
00278   sprintf(ArcName, "multi(0)disk(0)rdisk(%u)partition(0)", DriveNumber - 0x80);
00279   FsRegisterDevice(ArcName, &DiskVtbl);
00280 
00281   /* Add partitions */
00282   i = 1;
00283   DiskReportError(FALSE);
00284   while (XboxDiskGetPartitionEntry(DriveNumber, i, &PartitionTableEntry))
00285   {
00286     if (PartitionTableEntry.SystemIndicator != PARTITION_ENTRY_UNUSED)
00287     {
00288       sprintf(ArcName, "multi(0)disk(0)rdisk(%u)partition(%lu)", DriveNumber - 0x80, i);
00289       FsRegisterDevice(ArcName, &DiskVtbl);
00290     }
00291     i++;
00292   }
00293   DiskReportError(TRUE);
00294 
00295   /* Convert checksum and signature to identifier string */
00296   Identifier[0] = Hex[(Checksum >> 28) & 0x0F];
00297   Identifier[1] = Hex[(Checksum >> 24) & 0x0F];
00298   Identifier[2] = Hex[(Checksum >> 20) & 0x0F];
00299   Identifier[3] = Hex[(Checksum >> 16) & 0x0F];
00300   Identifier[4] = Hex[(Checksum >> 12) & 0x0F];
00301   Identifier[5] = Hex[(Checksum >> 8) & 0x0F];
00302   Identifier[6] = Hex[(Checksum >> 4) & 0x0F];
00303   Identifier[7] = Hex[Checksum & 0x0F];
00304   Identifier[8] = '-';
00305   Identifier[9] = Hex[(Signature >> 28) & 0x0F];
00306   Identifier[10] = Hex[(Signature >> 24) & 0x0F];
00307   Identifier[11] = Hex[(Signature >> 20) & 0x0F];
00308   Identifier[12] = Hex[(Signature >> 16) & 0x0F];
00309   Identifier[13] = Hex[(Signature >> 12) & 0x0F];
00310   Identifier[14] = Hex[(Signature >> 8) & 0x0F];
00311   Identifier[15] = Hex[(Signature >> 4) & 0x0F];
00312   Identifier[16] = Hex[Signature & 0x0F];
00313   Identifier[17] = '-';
00314   Identifier[18] = 'A';
00315   Identifier[19] = 0;
00316   TRACE("Identifier: %s\n", Identifier);
00317 }
00318 
00319 static VOID
00320 DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA SystemKey,
00321                 PCONFIGURATION_COMPONENT_DATA BusKey)
00322 {
00323     PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
00324     PCM_INT13_DRIVE_PARAMETER Int13Drives;
00325     GEOMETRY Geometry;
00326     PCONFIGURATION_COMPONENT_DATA DiskKey, ControllerKey;
00327     UCHAR DiskCount;
00328     USHORT i;
00329     ULONG Size;
00330     BOOLEAN Changed;
00331     
00332     /* Count the number of visible drives */
00333     DiskReportError(FALSE);
00334     DiskCount = 0;
00335     
00336     /* There are some really broken BIOSes out there. There are even BIOSes
00337         * that happily report success when you ask them to read from non-existent
00338         * harddisks. So, we set the buffer to known contents first, then try to
00339         * read. If the BIOS reports success but the buffer contents haven't
00340         * changed then we fail anyway */
00341     memset((PVOID) DISKREADBUFFER, 0xcd, DISKREADBUFFER_SIZE);
00342     while (MachDiskReadLogicalSectors(0x80 + DiskCount, 0ULL, 1, (PVOID)DISKREADBUFFER))
00343     {
00344         Changed = FALSE;
00345         for (i = 0; ! Changed && i < DISKREADBUFFER_SIZE; i++)
00346         {
00347             Changed = ((PUCHAR)DISKREADBUFFER)[i] != 0xcd;
00348         }
00349         if (! Changed)
00350         {
00351             TRACE("BIOS reports success for disk %d but data didn't change\n",
00352                   (int)DiskCount);
00353             break;
00354         }
00355         DiskCount++;
00356         memset((PVOID) DISKREADBUFFER, 0xcd, DISKREADBUFFER_SIZE);
00357     }
00358     DiskReportError(TRUE);
00359     TRACE("BIOS reports %d harddisk%s\n",
00360           (int)DiskCount, (DiskCount == 1) ? "": "s");
00361     
00362     //DetectBiosFloppyController(BusKey);
00363     
00364     /* Allocate resource descriptor */
00365     Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
00366         sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
00367     PartialResourceList = MmHeapAlloc(Size);
00368     if (PartialResourceList == NULL)
00369     {
00370         ERR("Failed to allocate resource descriptor\n");
00371         return;
00372     }
00373     
00374     /* Initialize resource descriptor */
00375     memset(PartialResourceList, 0, Size);
00376     PartialResourceList->Version = 1;
00377     PartialResourceList->Revision = 1;
00378     PartialResourceList->Count = 1;
00379     PartialResourceList->PartialDescriptors[0].Type = CmResourceTypeDeviceSpecific;
00380     PartialResourceList->PartialDescriptors[0].ShareDisposition = 0;
00381     PartialResourceList->PartialDescriptors[0].Flags = 0;
00382     PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
00383         sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
00384     
00385     /* Get harddisk Int13 geometry data */
00386     Int13Drives = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
00387     for (i = 0; i < DiskCount; i++)
00388     {
00389         if (MachDiskGetDriveGeometry(0x80 + i, &Geometry))
00390         {
00391             Int13Drives[i].DriveSelect = 0x80 + i;
00392             Int13Drives[i].MaxCylinders = Geometry.Cylinders - 1;
00393             Int13Drives[i].SectorsPerTrack = (USHORT)Geometry.Sectors;
00394             Int13Drives[i].MaxHeads = (USHORT)Geometry.Heads - 1;
00395             Int13Drives[i].NumberDrives = DiskCount;
00396             
00397             TRACE(
00398                       "Disk %x: %u Cylinders  %u Heads  %u Sectors  %u Bytes\n",
00399                       0x80 + i,
00400                       Geometry.Cylinders - 1,
00401                       Geometry.Heads -1,
00402                       Geometry.Sectors,
00403                       Geometry.BytesPerSector);
00404         }
00405     }
00406     
00407     FldrCreateComponentKey(BusKey,
00408                            ControllerClass,
00409                            DiskController,
00410                            Output | Input,
00411                            0,
00412                            0xFFFFFFFF,
00413                            NULL,
00414                            PartialResourceList,
00415                            Size,
00416                            &ControllerKey);
00417     TRACE("Created key: DiskController\\0\n");
00418     
00419     MmHeapFree(PartialResourceList);
00420     
00421     /* Create and fill subkey for each harddisk */
00422     for (i = 0; i < DiskCount; i++)
00423     {
00424         PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
00425         ULONG Size;
00426         CHAR Identifier[20];
00427 
00428         /* Get disk values */
00429         PartialResourceList = GetHarddiskConfigurationData(0x80 + i, &Size);
00430         GetHarddiskIdentifier(Identifier, 0x80 + i);
00431 
00432         /* Create disk key */
00433         FldrCreateComponentKey(ControllerKey,
00434                                PeripheralClass,
00435                                DiskPeripheral,
00436                                Output | Input,
00437                                0,
00438                                0xFFFFFFFF,
00439                                Identifier,
00440                                PartialResourceList,
00441                                Size,
00442                                &DiskKey);
00443 
00444         if (PartialResourceList)
00445             MmHeapFree(PartialResourceList);
00446     }
00447 }
00448 
00449 static VOID
00450 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
00451 {
00452   PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
00453   PCONFIGURATION_COMPONENT_DATA BusKey;
00454   ULONG Size;
00455 
00456   /* Set 'Configuration Data' value */
00457   Size = sizeof(CM_PARTIAL_RESOURCE_LIST) -
00458      sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
00459   PartialResourceList = MmHeapAlloc(Size);
00460   if (PartialResourceList == NULL)
00461     {
00462       TRACE(
00463         "Failed to allocate resource descriptor\n");
00464       return;
00465     }
00466 
00467   /* Initialize resource descriptor */
00468   memset(PartialResourceList, 0, Size);
00469   PartialResourceList->Version = 1;
00470   PartialResourceList->Revision = 1;
00471   PartialResourceList->Count = 0;
00472 
00473     /* Create new bus key */
00474     FldrCreateComponentKey(SystemKey,
00475                            AdapterClass,
00476                            MultiFunctionAdapter,
00477                            0x0,
00478                            0x0,
00479                            0xFFFFFFFF,
00480                            "ISA",
00481                            PartialResourceList,
00482                            Size,
00483                            &BusKey);
00484 
00485     /* Increment bus number */
00486     (*BusNumber)++;
00487 
00488   MmHeapFree(PartialResourceList);
00489 
00490   /* Detect ISA/BIOS devices */
00491   DetectBiosDisks(SystemKey, BusKey);
00492 
00493 
00494   /* FIXME: Detect more ISA devices */
00495 }
00496 
00497 PCONFIGURATION_COMPONENT_DATA
00498 XboxHwDetect(VOID)
00499 {
00500   PCONFIGURATION_COMPONENT_DATA SystemKey;
00501   ULONG BusNumber = 0;
00502 
00503   TRACE("DetectHardware()\n");
00504 
00505   /* Create the 'System' key */
00506   FldrCreateSystemKey(&SystemKey);
00507 
00508   /* TODO: Build actual xbox's hardware configuration tree */
00509   DetectIsaBios(SystemKey, &BusNumber);
00510 
00511   TRACE("DetectHardware() Done\n");
00512   return SystemKey;
00513 }
00514 
00515 VOID XboxHwIdle(VOID)
00516 {
00517     /* UNIMPLEMENTED */
00518 }
00519 
00520 /* EOF */

Generated on Sat May 26 2012 04:17:53 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.