Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenxboxhw.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
1.7.6.1
|