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
))
142 if (DrivePartition
== 0xff)
144 /* This is a CD-ROM device */
149 /* This is either a floppy disk device (DrivePartition == 0) or
150 * a hard disk device (DrivePartition != 0 && DrivePartition != 0xFF) but
151 * it doesn't matter which one because they both have 512 bytes per sector */
155 if (DrivePartition
!= 0xff && DrivePartition
!= 0)
157 if (!XboxDiskGetPartitionEntry(DriveNumber
, DrivePartition
, &PartitionTableEntry
))
159 SectorOffset
= PartitionTableEntry
.SectorCountBeforePartition
;
160 SectorCount
= PartitionTableEntry
.PartitionSectorCount
;
164 SectorCount
= 0; /* FIXME */
167 Context
= MmHeapAlloc(sizeof(DISKCONTEXT
));
170 Context
->DriveNumber
= DriveNumber
;
171 Context
->SectorSize
= SectorSize
;
172 Context
->SectorOffset
= SectorOffset
;
173 Context
->SectorCount
= SectorCount
;
174 Context
->SectorNumber
= 0;
175 FsSetDeviceSpecific(*FileId
, Context
);
180 static LONG
DiskRead(ULONG FileId
, VOID
* Buffer
, ULONG N
, ULONG
* Count
)
182 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
183 UCHAR
* Ptr
= (UCHAR
*)Buffer
;
184 ULONG i
, Length
, Sectors
;
192 if (Length
> DISKREADBUFFER_SIZE
)
193 Length
= DISKREADBUFFER_SIZE
;
194 Sectors
= (Length
+ Context
->SectorSize
- 1) / Context
->SectorSize
;
195 ret
= MachDiskReadLogicalSectors(
196 Context
->DriveNumber
,
197 Context
->SectorNumber
+ Context
->SectorOffset
+ i
,
199 (PVOID
)DISKREADBUFFER
);
202 RtlCopyMemory(Ptr
, (PVOID
)DISKREADBUFFER
, Length
);
212 static LONG
DiskSeek(ULONG FileId
, LARGE_INTEGER
* Position
, SEEKMODE SeekMode
)
214 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
216 if (SeekMode
!= SeekAbsolute
)
218 if (Position
->LowPart
& (Context
->SectorSize
- 1))
221 /* FIXME: take HighPart into account */
222 Context
->SectorNumber
= Position
->LowPart
/ Context
->SectorSize
;
226 static const DEVVTBL DiskVtbl
= {
228 DiskGetFileInformation
,
235 GetHarddiskIdentifier(PCHAR Identifier
,
238 PMASTER_BOOT_RECORD Mbr
;
244 PARTITION_TABLE_ENTRY PartitionTableEntry
;
247 if (!MachDiskReadLogicalSectors(DriveNumber
, 0ULL, 1, (PVOID
)DISKREADBUFFER
))
249 DPRINTM(DPRINT_HWDETECT
, "Reading MBR failed\n");
253 Buffer
= (ULONG
*)DISKREADBUFFER
;
254 Mbr
= (PMASTER_BOOT_RECORD
)DISKREADBUFFER
;
256 Signature
= Mbr
->Signature
;
257 DPRINTM(DPRINT_HWDETECT
, "Signature: %x\n", Signature
);
259 /* Calculate the MBR checksum */
261 for (i
= 0; i
< 128; i
++)
263 Checksum
+= Buffer
[i
];
265 Checksum
= ~Checksum
+ 1;
266 DPRINTM(DPRINT_HWDETECT
, "Checksum: %x\n", Checksum
);
268 /* Fill out the ARC disk block */
269 reactos_arc_disk_info
[reactos_disk_count
].Signature
= Signature
;
270 reactos_arc_disk_info
[reactos_disk_count
].CheckSum
= Checksum
;
271 sprintf(ArcName
, "multi(0)disk(0)rdisk(%lu)", reactos_disk_count
);
272 strcpy(reactos_arc_strings
[reactos_disk_count
], ArcName
);
273 reactos_arc_disk_info
[reactos_disk_count
].ArcName
=
274 reactos_arc_strings
[reactos_disk_count
];
275 reactos_disk_count
++;
277 sprintf(ArcName
, "multi(0)disk(0)rdisk(%lu)partition(0)", DriveNumber
- 0x80);
278 FsRegisterDevice(ArcName
, &DiskVtbl
);
282 DiskReportError(FALSE
);
283 while (XboxDiskGetPartitionEntry(DriveNumber
, i
, &PartitionTableEntry
))
285 if (PartitionTableEntry
.SystemIndicator
!= PARTITION_ENTRY_UNUSED
)
287 sprintf(ArcName
, "multi(0)disk(0)rdisk(%lu)partition(%lu)", DriveNumber
- 0x80, i
);
288 FsRegisterDevice(ArcName
, &DiskVtbl
);
292 DiskReportError(TRUE
);
294 /* Convert checksum and signature to identifier string */
295 Identifier
[0] = Hex
[(Checksum
>> 28) & 0x0F];
296 Identifier
[1] = Hex
[(Checksum
>> 24) & 0x0F];
297 Identifier
[2] = Hex
[(Checksum
>> 20) & 0x0F];
298 Identifier
[3] = Hex
[(Checksum
>> 16) & 0x0F];
299 Identifier
[4] = Hex
[(Checksum
>> 12) & 0x0F];
300 Identifier
[5] = Hex
[(Checksum
>> 8) & 0x0F];
301 Identifier
[6] = Hex
[(Checksum
>> 4) & 0x0F];
302 Identifier
[7] = Hex
[Checksum
& 0x0F];
304 Identifier
[9] = Hex
[(Signature
>> 28) & 0x0F];
305 Identifier
[10] = Hex
[(Signature
>> 24) & 0x0F];
306 Identifier
[11] = Hex
[(Signature
>> 20) & 0x0F];
307 Identifier
[12] = Hex
[(Signature
>> 16) & 0x0F];
308 Identifier
[13] = Hex
[(Signature
>> 12) & 0x0F];
309 Identifier
[14] = Hex
[(Signature
>> 8) & 0x0F];
310 Identifier
[15] = Hex
[(Signature
>> 4) & 0x0F];
311 Identifier
[16] = Hex
[Signature
& 0x0F];
312 Identifier
[17] = '-';
313 Identifier
[18] = 'A';
315 DPRINTM(DPRINT_HWDETECT
, "Identifier: %s\n", Identifier
);
319 DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA SystemKey
,
320 PCONFIGURATION_COMPONENT_DATA BusKey
)
322 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
323 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
325 PCONFIGURATION_COMPONENT_DATA DiskKey
, ControllerKey
;
331 /* Count the number of visible drives */
332 DiskReportError(FALSE
);
335 /* There are some really broken BIOSes out there. There are even BIOSes
336 * that happily report success when you ask them to read from non-existent
337 * harddisks. So, we set the buffer to known contents first, then try to
338 * read. If the BIOS reports success but the buffer contents haven't
339 * changed then we fail anyway */
340 memset((PVOID
) DISKREADBUFFER
, 0xcd, 512);
341 while (MachDiskReadLogicalSectors(0x80 + DiskCount
, 0ULL, 1, (PVOID
)DISKREADBUFFER
))
344 for (i
= 0; ! Changed
&& i
< 512; i
++)
346 Changed
= ((PUCHAR
)DISKREADBUFFER
)[i
] != 0xcd;
350 DPRINTM(DPRINT_HWDETECT
, "BIOS reports success for disk %d but data didn't change\n",
355 memset((PVOID
) DISKREADBUFFER
, 0xcd, 512);
357 DiskReportError(TRUE
);
358 DPRINTM(DPRINT_HWDETECT
, "BIOS reports %d harddisk%s\n",
359 (int)DiskCount
, (DiskCount
== 1) ? "": "s");
361 //DetectBiosFloppyController(BusKey);
363 /* Allocate resource descriptor */
364 Size
= sizeof(CM_PARTIAL_RESOURCE_LIST
) +
365 sizeof(CM_INT13_DRIVE_PARAMETER
) * DiskCount
;
366 PartialResourceList
= MmHeapAlloc(Size
);
367 if (PartialResourceList
== NULL
)
369 DPRINTM(DPRINT_HWDETECT
,
370 "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
= Geometry
.Sectors
;
394 Int13Drives
[i
].MaxHeads
= Geometry
.Heads
- 1;
395 Int13Drives
[i
].NumberDrives
= DiskCount
;
397 DPRINTM(DPRINT_HWDETECT
,
398 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
400 Geometry
.Cylinders
- 1,
403 Geometry
.BytesPerSector
);
407 FldrCreateComponentKey(BusKey
,
417 DPRINTM(DPRINT_HWDETECT
, "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
)
462 DPRINTM(DPRINT_HWDETECT
,
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 DPRINTM(DPRINT_HWDETECT
, "DetectHardware()\n");
505 /* Create the 'System' key */
506 FldrCreateSystemKey(&SystemKey
);
508 /* TODO: Build actual xbox's hardware configuration tree */
509 DetectIsaBios(SystemKey
, &BusNumber
);
511 DPRINTM(DPRINT_HWDETECT
, "DetectHardware() Done\n");