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 static CHAR Hex
[] = "0123456789ABCDEF";
26 //static unsigned int delay_count = 1;
28 extern ULONG reactos_disk_count
;
29 extern ARC_DISK_SIGNATURE reactos_arc_disk_info
[];
30 extern char reactos_arc_strings
[32][256];
32 static PCM_PARTIAL_RESOURCE_LIST
33 GetHarddiskConfigurationData(ULONG DriveNumber
, ULONG
* pSize
)
35 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
36 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
37 EXTENDED_GEOMETRY ExtGeometry
;
42 // Initialize returned size
46 /* Set 'Configuration Data' value */
47 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
48 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
49 PartialResourceList
= MmHeapAlloc(Size
);
50 if (PartialResourceList
== NULL
)
52 DPRINTM(DPRINT_HWDETECT
,
53 "Failed to allocate a full resource descriptor\n");
57 memset(PartialResourceList
, 0, Size
);
58 PartialResourceList
->Version
= 1;
59 PartialResourceList
->Revision
= 1;
60 PartialResourceList
->Count
= 1;
61 PartialResourceList
->PartialDescriptors
[0].Type
=
62 CmResourceTypeDeviceSpecific
;
63 // PartialResourceList->PartialDescriptors[0].ShareDisposition =
64 // PartialResourceList->PartialDescriptors[0].Flags =
65 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
66 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
);
68 /* Get pointer to geometry data */
69 DiskGeometry
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
71 /* Get the disk geometry */
72 ExtGeometry
.Size
= sizeof(EXTENDED_GEOMETRY
);
74 if(MachDiskGetDriveGeometry(DriveNumber
, &Geometry
))
76 DiskGeometry
->BytesPerSector
= Geometry
.BytesPerSector
;
77 DiskGeometry
->NumberOfCylinders
= Geometry
.Cylinders
;
78 DiskGeometry
->SectorsPerTrack
= Geometry
.Sectors
;
79 DiskGeometry
->NumberOfHeads
= Geometry
.Heads
;
83 DPRINTM(DPRINT_HWDETECT
, "Reading disk geometry failed\n");
84 MmHeapFree(PartialResourceList
);
87 DPRINTM(DPRINT_HWDETECT
,
88 "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
.LowPart
= (Context
->SectorOffset
+ Context
->SectorNumber
) * Context
->SectorSize
;
130 static LONG
DiskOpen(CHAR
* Path
, OPENMODE OpenMode
, ULONG
* FileId
)
132 DISKCONTEXT
* Context
;
133 ULONG DriveNumber
, DrivePartition
, SectorSize
;
134 ULONGLONG SectorOffset
= 0;
135 ULONGLONG SectorCount
= 0;
136 PARTITION_TABLE_ENTRY PartitionTableEntry
;
139 if (!DissectArcPath(Path
, FileName
, &DriveNumber
, &DrivePartition
))
141 SectorSize
= (DrivePartition
== 0xff ? 2048 : 512);
142 if (DrivePartition
!= 0xff && DrivePartition
!= 0)
144 if (!XboxDiskGetPartitionEntry(DriveNumber
, DrivePartition
, &PartitionTableEntry
))
146 SectorOffset
= PartitionTableEntry
.SectorCountBeforePartition
;
147 SectorCount
= PartitionTableEntry
.PartitionSectorCount
;
151 SectorCount
= 0; /* FIXME */
154 Context
= MmHeapAlloc(sizeof(DISKCONTEXT
));
157 Context
->DriveNumber
= DriveNumber
;
158 Context
->SectorSize
= SectorSize
;
159 Context
->SectorOffset
= SectorOffset
;
160 Context
->SectorCount
= SectorCount
;
161 Context
->SectorNumber
= 0;
162 FsSetDeviceSpecific(*FileId
, Context
);
167 static LONG
DiskRead(ULONG FileId
, VOID
* Buffer
, ULONG N
, ULONG
* Count
)
169 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
170 UCHAR
* Ptr
= (UCHAR
*)Buffer
;
171 ULONG i
, Length
, Sectors
;
179 if (Length
> DISKREADBUFFER_SIZE
)
180 Length
= DISKREADBUFFER_SIZE
;
181 Sectors
= (Length
+ Context
->SectorSize
- 1) / Context
->SectorSize
;
182 ret
= MachDiskReadLogicalSectors(
183 Context
->DriveNumber
,
184 Context
->SectorNumber
+ Context
->SectorOffset
+ i
,
186 (PVOID
)DISKREADBUFFER
);
189 RtlCopyMemory(Ptr
, (PVOID
)DISKREADBUFFER
, Length
);
199 static LONG
DiskSeek(ULONG FileId
, LARGE_INTEGER
* Position
, SEEKMODE SeekMode
)
201 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
203 if (SeekMode
!= SeekAbsolute
)
205 if (Position
->LowPart
& (Context
->SectorSize
- 1))
208 /* FIXME: take HighPart into account */
209 Context
->SectorNumber
= Position
->LowPart
/ Context
->SectorSize
;
213 static const DEVVTBL DiskVtbl
= {
215 DiskGetFileInformation
,
222 GetHarddiskIdentifier(PCHAR Identifier
,
225 PMASTER_BOOT_RECORD Mbr
;
231 PARTITION_TABLE_ENTRY PartitionTableEntry
;
234 if (!MachDiskReadLogicalSectors(DriveNumber
, 0ULL, 1, (PVOID
)DISKREADBUFFER
))
236 DPRINTM(DPRINT_HWDETECT
, "Reading MBR failed\n");
240 Buffer
= (ULONG
*)DISKREADBUFFER
;
241 Mbr
= (PMASTER_BOOT_RECORD
)DISKREADBUFFER
;
243 Signature
= Mbr
->Signature
;
244 DPRINTM(DPRINT_HWDETECT
, "Signature: %x\n", Signature
);
246 /* Calculate the MBR checksum */
248 for (i
= 0; i
< 128; i
++)
250 Checksum
+= Buffer
[i
];
252 Checksum
= ~Checksum
+ 1;
253 DPRINTM(DPRINT_HWDETECT
, "Checksum: %x\n", Checksum
);
255 /* Fill out the ARC disk block */
256 reactos_arc_disk_info
[reactos_disk_count
].Signature
= Signature
;
257 reactos_arc_disk_info
[reactos_disk_count
].CheckSum
= Checksum
;
258 sprintf(ArcName
, "multi(0)disk(0)rdisk(%lu)", reactos_disk_count
);
259 strcpy(reactos_arc_strings
[reactos_disk_count
], ArcName
);
260 reactos_arc_disk_info
[reactos_disk_count
].ArcName
=
261 reactos_arc_strings
[reactos_disk_count
];
262 reactos_disk_count
++;
264 sprintf(ArcName
, "multi(0)disk(0)rdisk(%lu)partition(0)", DriveNumber
- 0x80);
265 FsRegisterDevice(ArcName
, &DiskVtbl
);
269 DiskReportError(FALSE
);
270 while (XboxDiskGetPartitionEntry(DriveNumber
, i
, &PartitionTableEntry
))
272 if (PartitionTableEntry
.SystemIndicator
!= PARTITION_ENTRY_UNUSED
)
274 sprintf(ArcName
, "multi(0)disk(0)rdisk(%lu)partition(%lu)", DriveNumber
- 0x80, i
);
275 FsRegisterDevice(ArcName
, &DiskVtbl
);
279 DiskReportError(TRUE
);
281 /* Convert checksum and signature to identifier string */
282 Identifier
[0] = Hex
[(Checksum
>> 28) & 0x0F];
283 Identifier
[1] = Hex
[(Checksum
>> 24) & 0x0F];
284 Identifier
[2] = Hex
[(Checksum
>> 20) & 0x0F];
285 Identifier
[3] = Hex
[(Checksum
>> 16) & 0x0F];
286 Identifier
[4] = Hex
[(Checksum
>> 12) & 0x0F];
287 Identifier
[5] = Hex
[(Checksum
>> 8) & 0x0F];
288 Identifier
[6] = Hex
[(Checksum
>> 4) & 0x0F];
289 Identifier
[7] = Hex
[Checksum
& 0x0F];
291 Identifier
[9] = Hex
[(Signature
>> 28) & 0x0F];
292 Identifier
[10] = Hex
[(Signature
>> 24) & 0x0F];
293 Identifier
[11] = Hex
[(Signature
>> 20) & 0x0F];
294 Identifier
[12] = Hex
[(Signature
>> 16) & 0x0F];
295 Identifier
[13] = Hex
[(Signature
>> 12) & 0x0F];
296 Identifier
[14] = Hex
[(Signature
>> 8) & 0x0F];
297 Identifier
[15] = Hex
[(Signature
>> 4) & 0x0F];
298 Identifier
[16] = Hex
[Signature
& 0x0F];
299 Identifier
[17] = '-';
300 Identifier
[18] = 'A';
302 DPRINTM(DPRINT_HWDETECT
, "Identifier: %s\n", Identifier
);
306 DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA SystemKey
,
307 PCONFIGURATION_COMPONENT_DATA BusKey
)
309 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
310 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
312 PCONFIGURATION_COMPONENT_DATA DiskKey
, ControllerKey
;
318 /* Count the number of visible drives */
319 DiskReportError(FALSE
);
322 /* There are some really broken BIOSes out there. There are even BIOSes
323 * that happily report success when you ask them to read from non-existent
324 * harddisks. So, we set the buffer to known contents first, then try to
325 * read. If the BIOS reports success but the buffer contents haven't
326 * changed then we fail anyway */
327 memset((PVOID
) DISKREADBUFFER
, 0xcd, 512);
328 while (MachDiskReadLogicalSectors(0x80 + DiskCount
, 0ULL, 1, (PVOID
)DISKREADBUFFER
))
331 for (i
= 0; ! Changed
&& i
< 512; i
++)
333 Changed
= ((PUCHAR
)DISKREADBUFFER
)[i
] != 0xcd;
337 DPRINTM(DPRINT_HWDETECT
, "BIOS reports success for disk %d but data didn't change\n",
342 memset((PVOID
) DISKREADBUFFER
, 0xcd, 512);
344 DiskReportError(TRUE
);
345 DPRINTM(DPRINT_HWDETECT
, "BIOS reports %d harddisk%s\n",
346 (int)DiskCount
, (DiskCount
== 1) ? "": "s");
348 //DetectBiosFloppyController(BusKey);
350 /* Allocate resource descriptor */
351 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
352 sizeof(CM_INT13_DRIVE_PARAMETER
) * DiskCount
;
353 PartialResourceList
= MmHeapAlloc(Size
);
354 if (PartialResourceList
== NULL
)
356 DPRINTM(DPRINT_HWDETECT
,
357 "Failed to allocate resource descriptor\n");
361 /* Initialize resource descriptor */
362 memset(PartialResourceList
, 0, Size
);
363 PartialResourceList
->Version
= 1;
364 PartialResourceList
->Revision
= 1;
365 PartialResourceList
->Count
= 1;
366 PartialResourceList
->PartialDescriptors
[0].Type
= CmResourceTypeDeviceSpecific
;
367 PartialResourceList
->PartialDescriptors
[0].ShareDisposition
= 0;
368 PartialResourceList
->PartialDescriptors
[0].Flags
= 0;
369 PartialResourceList
->PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
=
370 sizeof(CM_INT13_DRIVE_PARAMETER
) * DiskCount
;
372 /* Get harddisk Int13 geometry data */
373 Int13Drives
= (PVOID
)(((ULONG_PTR
)PartialResourceList
) + sizeof(CM_PARTIAL_RESOURCE_LIST
));
374 for (i
= 0; i
< DiskCount
; i
++)
376 if (MachDiskGetDriveGeometry(0x80 + i
, &Geometry
))
378 Int13Drives
[i
].DriveSelect
= 0x80 + i
;
379 Int13Drives
[i
].MaxCylinders
= Geometry
.Cylinders
- 1;
380 Int13Drives
[i
].SectorsPerTrack
= Geometry
.Sectors
;
381 Int13Drives
[i
].MaxHeads
= Geometry
.Heads
- 1;
382 Int13Drives
[i
].NumberDrives
= DiskCount
;
384 DPRINTM(DPRINT_HWDETECT
,
385 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
387 Geometry
.Cylinders
- 1,
390 Geometry
.BytesPerSector
);
394 FldrCreateComponentKey(BusKey
,
404 DPRINTM(DPRINT_HWDETECT
, "Created key: DiskController\\0\n");
406 MmHeapFree(PartialResourceList
);
408 /* Create and fill subkey for each harddisk */
409 for (i
= 0; i
< DiskCount
; i
++)
411 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
415 /* Get disk values */
416 PartialResourceList
= GetHarddiskConfigurationData(0x80 + i
, &Size
);
417 GetHarddiskIdentifier(Identifier
, 0x80 + i
);
419 /* Create disk key */
420 FldrCreateComponentKey(ControllerKey
,
431 if (PartialResourceList
)
432 MmHeapFree(PartialResourceList
);
437 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
439 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
440 PCONFIGURATION_COMPONENT_DATA BusKey
;
443 /* Set 'Configuration Data' value */
444 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) -
445 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
446 PartialResourceList
= MmHeapAlloc(Size
);
447 if (PartialResourceList
== NULL
)
449 DPRINTM(DPRINT_HWDETECT
,
450 "Failed to allocate resource descriptor\n");
454 /* Initialize resource descriptor */
455 memset(PartialResourceList
, 0, Size
);
456 PartialResourceList
->Version
= 1;
457 PartialResourceList
->Revision
= 1;
458 PartialResourceList
->Count
= 0;
460 /* Create new bus key */
461 FldrCreateComponentKey(SystemKey
,
463 MultiFunctionAdapter
,
472 /* Increment bus number */
475 MmHeapFree(PartialResourceList
);
477 /* Detect ISA/BIOS devices */
478 DetectBiosDisks(SystemKey
, BusKey
);
481 /* FIXME: Detect more ISA devices */
484 PCONFIGURATION_COMPONENT_DATA
487 PCONFIGURATION_COMPONENT_DATA SystemKey
;
490 DPRINTM(DPRINT_HWDETECT
, "DetectHardware()\n");
492 /* Create the 'System' key */
493 FldrCreateSystemKey(&SystemKey
);
495 /* TODO: Build actual xbox's hardware configuration tree */
496 DetectIsaBios(SystemKey
, &BusNumber
);
498 DPRINTM(DPRINT_HWDETECT
, "DetectHardware() Done\n");