5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 DBG_DEFAULT_CHANNEL(HWDETECT
);
27 static CHAR Hex
[] = "0123456789ABCDEF";
28 //static unsigned int delay_count = 1;
30 extern ULONG reactos_disk_count
;
31 extern ARC_DISK_SIGNATURE reactos_arc_disk_info
[];
32 extern char reactos_arc_strings
[32][256];
34 static PCM_PARTIAL_RESOURCE_LIST
35 GetHarddiskConfigurationData(UCHAR DriveNumber
, ULONG
* pSize
)
37 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
38 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
39 //EXTENDED_GEOMETRY ExtGeometry;
44 // Initialize returned size
48 /* Set 'Configuration Data' value */
49 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
50 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
51 PartialResourceList
= MmHeapAlloc(Size
);
52 if (PartialResourceList
== NULL
)
54 ERR("Failed to allocate a full resource descriptor\n");
58 memset(PartialResourceList
, 0, Size
);
59 PartialResourceList
->Version
= 1;
60 PartialResourceList
->Revision
= 1;
61 PartialResourceList
->Count
= 1;
62 PartialResourceList
->PartialDescriptors
[0].Type
=
63 CmResourceTypeDeviceSpecific
;
64 // PartialResourceList->PartialDescriptors[0].ShareDisposition =
65 // PartialResourceList->PartialDescriptors[0].Flags =
66 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
67 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
69 /* Get pointer to geometry data */
70 DiskGeometry
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
72 /* Get the disk geometry */
73 //ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);
75 if(MachDiskGetDriveGeometry(DriveNumber
, &Geometry
))
77 DiskGeometry
->BytesPerSector
= Geometry
.BytesPerSector
;
78 DiskGeometry
->NumberOfCylinders
= Geometry
.Cylinders
;
79 DiskGeometry
->SectorsPerTrack
= Geometry
.Sectors
;
80 DiskGeometry
->NumberOfHeads
= Geometry
.Heads
;
84 ERR("Reading disk geometry failed\n");
85 MmHeapFree(PartialResourceList
);
88 TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
90 DiskGeometry
->NumberOfCylinders
,
91 DiskGeometry
->NumberOfHeads
,
92 DiskGeometry
->SectorsPerTrack
,
93 DiskGeometry
->BytesPerSector
);
96 // Return configuration data
99 return PartialResourceList
;
102 typedef struct tagDISKCONTEXT
106 ULONGLONG SectorOffset
;
107 ULONGLONG SectorCount
;
108 ULONGLONG SectorNumber
;
111 static LONG
DiskClose(ULONG FileId
)
113 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
119 static LONG
DiskGetFileInformation(ULONG FileId
, FILEINFORMATION
* Information
)
121 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
123 RtlZeroMemory(Information
, sizeof(FILEINFORMATION
));
124 Information
->EndingAddress
.QuadPart
= (Context
->SectorOffset
+ Context
->SectorCount
) * Context
->SectorSize
;
125 Information
->CurrentAddress
.QuadPart
= (Context
->SectorOffset
+ Context
->SectorNumber
) * Context
->SectorSize
;
130 static LONG
DiskOpen(CHAR
* Path
, OPENMODE OpenMode
, ULONG
* FileId
)
132 DISKCONTEXT
* Context
;
133 ULONG DrivePartition
, SectorSize
;
135 ULONGLONG SectorOffset
= 0;
136 ULONGLONG SectorCount
= 0;
137 PARTITION_TABLE_ENTRY PartitionTableEntry
;
140 if (!DissectArcPath(Path
, FileName
, &DriveNumber
, &DrivePartition
))
143 if (DrivePartition
== 0xff)
145 /* This is a CD-ROM device */
150 /* This is either a floppy disk device (DrivePartition == 0) or
151 * a hard disk device (DrivePartition != 0 && DrivePartition != 0xFF) but
152 * it doesn't matter which one because they both have 512 bytes per sector */
156 if (DrivePartition
!= 0xff && DrivePartition
!= 0)
158 if (!XboxDiskGetPartitionEntry(DriveNumber
, DrivePartition
, &PartitionTableEntry
))
160 SectorOffset
= PartitionTableEntry
.SectorCountBeforePartition
;
161 SectorCount
= PartitionTableEntry
.PartitionSectorCount
;
165 SectorCount
= 0; /* FIXME */
168 Context
= MmHeapAlloc(sizeof(DISKCONTEXT
));
171 Context
->DriveNumber
= DriveNumber
;
172 Context
->SectorSize
= SectorSize
;
173 Context
->SectorOffset
= SectorOffset
;
174 Context
->SectorCount
= SectorCount
;
175 Context
->SectorNumber
= 0;
176 FsSetDeviceSpecific(*FileId
, Context
);
181 static LONG
DiskRead(ULONG FileId
, VOID
* Buffer
, ULONG N
, ULONG
* Count
)
183 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
184 UCHAR
* Ptr
= (UCHAR
*)Buffer
;
185 ULONG i
, Length
, Sectors
;
193 if (Length
> DISKREADBUFFER_SIZE
)
194 Length
= DISKREADBUFFER_SIZE
;
195 Sectors
= (Length
+ Context
->SectorSize
- 1) / Context
->SectorSize
;
196 ret
= MachDiskReadLogicalSectors(
197 Context
->DriveNumber
,
198 Context
->SectorNumber
+ Context
->SectorOffset
+ i
,
200 (PVOID
)DISKREADBUFFER
);
203 RtlCopyMemory(Ptr
, (PVOID
)DISKREADBUFFER
, Length
);
213 static LONG
DiskSeek(ULONG FileId
, LARGE_INTEGER
* Position
, SEEKMODE SeekMode
)
215 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
217 if (SeekMode
!= SeekAbsolute
)
219 if (Position
->LowPart
& (Context
->SectorSize
- 1))
222 /* FIXME: take HighPart into account */
223 Context
->SectorNumber
= Position
->LowPart
/ Context
->SectorSize
;
227 static const DEVVTBL DiskVtbl
= {
229 DiskGetFileInformation
,
236 GetHarddiskIdentifier(PCHAR Identifier
,
239 PMASTER_BOOT_RECORD Mbr
;
245 PARTITION_TABLE_ENTRY PartitionTableEntry
;
248 if (!MachDiskReadLogicalSectors(DriveNumber
, 0ULL, 1, (PVOID
)DISKREADBUFFER
))
250 ERR("Reading MBR failed\n");
254 Buffer
= (ULONG
*)DISKREADBUFFER
;
255 Mbr
= (PMASTER_BOOT_RECORD
)DISKREADBUFFER
;
257 Signature
= Mbr
->Signature
;
258 TRACE("Signature: %x\n", Signature
);
260 /* Calculate the MBR checksum */
262 for (i
= 0; i
< 128; i
++)
264 Checksum
+= Buffer
[i
];
266 Checksum
= ~Checksum
+ 1;
267 TRACE("Checksum: %x\n", Checksum
);
269 /* Fill out the ARC disk block */
270 reactos_arc_disk_info
[reactos_disk_count
].Signature
= Signature
;
271 reactos_arc_disk_info
[reactos_disk_count
].CheckSum
= Checksum
;
272 sprintf(ArcName
, "multi(0)disk(0)rdisk(%lu)", reactos_disk_count
);
273 strcpy(reactos_arc_strings
[reactos_disk_count
], ArcName
);
274 reactos_arc_disk_info
[reactos_disk_count
].ArcName
=
275 reactos_arc_strings
[reactos_disk_count
];
276 reactos_disk_count
++;
278 sprintf(ArcName
, "multi(0)disk(0)rdisk(%u)partition(0)", DriveNumber
- 0x80);
279 FsRegisterDevice(ArcName
, &DiskVtbl
);
283 DiskReportError(FALSE
);
284 while (XboxDiskGetPartitionEntry(DriveNumber
, i
, &PartitionTableEntry
))
286 if (PartitionTableEntry
.SystemIndicator
!= PARTITION_ENTRY_UNUSED
)
288 sprintf(ArcName
, "multi(0)disk(0)rdisk(%u)partition(%lu)", DriveNumber
- 0x80, i
);
289 FsRegisterDevice(ArcName
, &DiskVtbl
);
293 DiskReportError(TRUE
);
295 /* Convert checksum and signature to identifier string */
296 Identifier
[0] = Hex
[(Checksum
>> 28) & 0x0F];
297 Identifier
[1] = Hex
[(Checksum
>> 24) & 0x0F];
298 Identifier
[2] = Hex
[(Checksum
>> 20) & 0x0F];
299 Identifier
[3] = Hex
[(Checksum
>> 16) & 0x0F];
300 Identifier
[4] = Hex
[(Checksum
>> 12) & 0x0F];
301 Identifier
[5] = Hex
[(Checksum
>> 8) & 0x0F];
302 Identifier
[6] = Hex
[(Checksum
>> 4) & 0x0F];
303 Identifier
[7] = Hex
[Checksum
& 0x0F];
305 Identifier
[9] = Hex
[(Signature
>> 28) & 0x0F];
306 Identifier
[10] = Hex
[(Signature
>> 24) & 0x0F];
307 Identifier
[11] = Hex
[(Signature
>> 20) & 0x0F];
308 Identifier
[12] = Hex
[(Signature
>> 16) & 0x0F];
309 Identifier
[13] = Hex
[(Signature
>> 12) & 0x0F];
310 Identifier
[14] = Hex
[(Signature
>> 8) & 0x0F];
311 Identifier
[15] = Hex
[(Signature
>> 4) & 0x0F];
312 Identifier
[16] = Hex
[Signature
& 0x0F];
313 Identifier
[17] = '-';
314 Identifier
[18] = 'A';
316 TRACE("Identifier: %s\n", Identifier
);
320 DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA SystemKey
,
321 PCONFIGURATION_COMPONENT_DATA BusKey
)
323 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
324 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
326 PCONFIGURATION_COMPONENT_DATA DiskKey
, ControllerKey
;
332 /* Count the number of visible drives */
333 DiskReportError(FALSE
);
336 /* There are some really broken BIOSes out there. There are even BIOSes
337 * that happily report success when you ask them to read from non-existent
338 * harddisks. So, we set the buffer to known contents first, then try to
339 * read. If the BIOS reports success but the buffer contents haven't
340 * changed then we fail anyway */
341 memset((PVOID
) DISKREADBUFFER
, 0xcd, DISKREADBUFFER_SIZE
);
342 while (MachDiskReadLogicalSectors(0x80 + DiskCount
, 0ULL, 1, (PVOID
)DISKREADBUFFER
))
345 for (i
= 0; ! Changed
&& i
< DISKREADBUFFER_SIZE
; i
++)
347 Changed
= ((PUCHAR
)DISKREADBUFFER
)[i
] != 0xcd;
351 TRACE("BIOS reports success for disk %d but data didn't change\n",
356 memset((PVOID
) DISKREADBUFFER
, 0xcd, DISKREADBUFFER_SIZE
);
358 DiskReportError(TRUE
);
359 TRACE("BIOS reports %d harddisk%s\n",
360 (int)DiskCount
, (DiskCount
== 1) ? "": "s");
362 //DetectBiosFloppyController(BusKey);
364 /* Allocate resource descriptor */
365 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
366 sizeof(CM_INT13_DRIVE_PARAMETER
) * DiskCount
;
367 PartialResourceList
= MmHeapAlloc(Size
);
368 if (PartialResourceList
== NULL
)
370 ERR("Failed to allocate resource descriptor\n");
374 /* Initialize resource descriptor */
375 memset(PartialResourceList
, 0, Size
);
376 PartialResourceList
->Version
= 1;
377 PartialResourceList
->Revision
= 1;
378 PartialResourceList
->Count
= 1;
379 PartialResourceList
->PartialDescriptors
[0].Type
= CmResourceTypeDeviceSpecific
;
380 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
= 0;
381 PartialResourceList
->PartialDescriptors
[0].Flags
= 0;
382 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
383 sizeof(CM_INT13_DRIVE_PARAMETER
) * DiskCount
;
385 /* Get harddisk Int13 geometry data */
386 Int13Drives
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
387 for (i
= 0; i
< DiskCount
; i
++)
389 if (MachDiskGetDriveGeometry(0x80 + i
, &Geometry
))
391 Int13Drives
[i
].DriveSelect
= 0x80 + i
;
392 Int13Drives
[i
].MaxCylinders
= Geometry
.Cylinders
- 1;
393 Int13Drives
[i
].SectorsPerTrack
= (USHORT
)Geometry
.Sectors
;
394 Int13Drives
[i
].MaxHeads
= (USHORT
)Geometry
.Heads
- 1;
395 Int13Drives
[i
].NumberDrives
= DiskCount
;
398 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
400 Geometry
.Cylinders
- 1,
403 Geometry
.BytesPerSector
);
407 FldrCreateComponentKey(BusKey
,
417 TRACE("Created key: DiskController\\0\n");
419 MmHeapFree(PartialResourceList
);
421 /* Create and fill subkey for each harddisk */
422 for (i
= 0; i
< DiskCount
; i
++)
424 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
428 /* Get disk values */
429 PartialResourceList
= GetHarddiskConfigurationData(0x80 + i
, &Size
);
430 GetHarddiskIdentifier(Identifier
, 0x80 + i
);
432 /* Create disk key */
433 FldrCreateComponentKey(ControllerKey
,
444 if (PartialResourceList
)
445 MmHeapFree(PartialResourceList
);
450 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
452 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
453 PCONFIGURATION_COMPONENT_DATA BusKey
;
456 /* Set 'Configuration Data' value */
457 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
458 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
459 PartialResourceList
= MmHeapAlloc(Size
);
460 if (PartialResourceList
== NULL
)
463 "Failed to allocate resource descriptor\n");
467 /* Initialize resource descriptor */
468 memset(PartialResourceList
, 0, Size
);
469 PartialResourceList
->Version
= 1;
470 PartialResourceList
->Revision
= 1;
471 PartialResourceList
->Count
= 0;
473 /* Create new bus key */
474 FldrCreateComponentKey(SystemKey
,
476 MultiFunctionAdapter
,
485 /* Increment bus number */
488 MmHeapFree(PartialResourceList
);
490 /* Detect ISA/BIOS devices */
491 DetectBiosDisks(SystemKey
, BusKey
);
494 /* FIXME: Detect more ISA devices */
497 PCONFIGURATION_COMPONENT_DATA
500 PCONFIGURATION_COMPONENT_DATA SystemKey
;
503 TRACE("DetectHardware()\n");
505 /* Create the 'System' key */
506 FldrCreateSystemKey(&SystemKey
);
508 /* TODO: Build actual xbox's hardware configuration tree */
509 DetectIsaBios(SystemKey
, &BusNumber
);
511 TRACE("DetectHardware() Done\n");
515 VOID
XboxHwIdle(VOID
)