ReactOS 0.4.16-dev-2613-g9533ad7
pc98disk.c
Go to the documentation of this file.
1/*
2 * PROJECT: FreeLoader
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Drive access routines for NEC PC-98 series
5 * COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean@protonmail.com)
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include <freeldr.h>
11#include <hwide.h>
12
13#include <debug.h>
15
16/* GLOBALS ********************************************************************/
17
18/* Maximum number of disks, indexed from 0x00 to 0xFF */
19#define MAX_DRIVES 0x100
20
21/* Cache of all possible PC disk drives */
23
24/* DISK IO ERROR SUPPORT ******************************************************/
25
26/* For disk.c!DiskError() */
30{
31 switch (ErrorCode & 0xF0)
32 {
33 case 0x00: return "No error";
34 case 0x10: return "Drive write protection error";
35 case 0x20: return "DMA access across 64 kB boundary";
36 case 0x30: return "End of cylinder";
37 case 0x40: return "The drive name is invalid or the device have low health";
38 case 0x50: return "Time out, data not written";
39 case 0x60: return "Time out, drive not ready";
40 case 0x70:
41 if (ErrorCode == 0x78)
42 return "Illegal disk address";
43 else
44 return "Drive write protection error";
45 case 0x80: return "Undefined error";
46 case 0x90: return "Time out error";
47 case 0xA0: return "CRC error in the ID section";
48 case 0xB0: return "CRC error in the DATA section";
49 case 0xC0:
50 if (ErrorCode == 0xC8)
51 return "Seek failure";
52 else
53 return "No data (Sector not found)";
54 case 0xD0: return "Bad cylinder";
55 case 0xE0: return "No ID address mark was found";
56 case 0xF0: return "No DATA address mark was found";
57
58 default: return "Unknown error code";
59 }
60}
61
62/* FUNCTIONS ******************************************************************/
63
64static
67 _In_ PPC98_DISK_DRIVE DiskDrive)
68{
69 REGS Regs;
70
71 if (DiskDrive->Type == DRIVE_TYPE_FDD)
72 {
73 /* Int 1Bh AH=07h
74 * DISK BIOS - Recalibrate
75 *
76 * Call with:
77 * AL - drive number
78 *
79 * Return:
80 * CF - set on error, clear if successful
81 * AH - status
82 */
83 Regs.b.ah = 0x07;
84 }
85 else if (DiskDrive->Type == DRIVE_TYPE_HDD)
86 {
87 /* Int 1Bh AH=03h
88 * DISK BIOS - Initialize
89 *
90 * Call with:
91 * AL - drive number
92 *
93 * Return:
94 * CF - set on error, clear if successful
95 * AH - status
96 */
97 Regs.b.ah = 0x03;
98 }
99 else
100 {
101 return FALSE;
102 }
103
104 WARN("DiskResetController(0x%x) DISK OPERATION FAILED -- RESETTING CONTROLLER\n",
105 DiskDrive->DaUa);
106
107 Regs.b.al = DiskDrive->DaUa;
108 Int386(0x1B, &Regs, &Regs);
109 return INT386_SUCCESS(Regs);
110}
111
114 _In_ UCHAR DriveNumber)
115{
116 PPC98_DISK_DRIVE DiskDrive;
117
118 ASSERT(DriveNumber < RTL_NUMBER_OF(Pc98DiskDrive));
119
120 /* Retrieve a slot */
121 DiskDrive = &Pc98DiskDrive[DriveNumber];
122
123 /* The pre-initialization of the BIOS disks was already done in Pc98InitializeBootDevices() */
124 if (DiskDrive->Flags & DRIVE_FLAGS_INITIALIZED)
125 return DiskDrive;
126 else
127 return NULL;
128}
129
132 _In_ UCHAR DriveNumber)
133{
134 PPC98_DISK_DRIVE DiskDrive;
135
136 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber);
137 if (!DiskDrive)
138 return -1; // MaximumType;
139
140 if (DiskDrive->Type == DRIVE_TYPE_CDROM)
141 return CdromController;
142 else if (DiskDrive->Type == DRIVE_TYPE_FDD)
144 else
145 return DiskPeripheral;
146}
147
148static
149UCHAR
151 _In_ ULONG BytesPerSector)
152{
153 switch (BytesPerSector)
154 {
155 case 128:
156 return 0;
157 case 256:
158 return 1;
159 case 512:
160 return 2;
161 case 1024:
162 return 3;
163 case 2048:
164 return 4;
165 default:
166 return 0;
167 }
168}
169
170static
173 _In_ PPC98_DISK_DRIVE DiskDrive,
174 _In_ ULONG64 SectorNumber,
176 _Out_writes_bytes_all_(SectorCount * DiskDrive->Geometry.BytesPerSector) PVOID Buffer)
177{
178 REGS RegsIn, RegsOut;
179 ULONG RetryCount;
180
181 /* Int 1Bh AH=06h
182 * DISK BIOS - Read data
183 *
184 * Call with:
185 * AL - drive number
186 * BX - bytes to read
187 * CX - cylinder number
188 * DH - head number
189 * DL - sector number
190 * ES:BP -> buffer to read data into
191 *
192 * Return:
193 * CF - set on error, clear if successful
194 * AH - status
195 */
196 RegsIn.b.al = DiskDrive->DaUa;
197 RegsIn.b.ah = 0x06;
198 RegsIn.w.bx = DiskDrive->Geometry.BytesPerSector * SectorCount;
199 RegsIn.w.cx = SectorNumber & 0xFFFF;
200 RegsIn.w.dx = (SectorNumber >> 16) & 0xFFFF;
201 RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4);
202 RegsIn.w.bp = ((ULONG_PTR)Buffer) & 0x0F;
203
204 /* Retry 3 times */
205 for (RetryCount = 0; RetryCount < 3; ++RetryCount)
206 {
207 Int386(0x1B, &RegsIn, &RegsOut);
208
209 /* If it worked, or if it was a corrected ECC error
210 * and the data is still good, return success */
211 if (INT386_SUCCESS(RegsOut) || (RegsOut.b.ah == 0x08))
212 return TRUE;
213
214 /* It failed, do the next retry */
215 DiskResetController(DiskDrive);
216 }
217
218 /* If we get here then the read failed */
219 DiskError("Disk Read Failed in LBA mode", RegsOut.b.ah);
220 ERR("Disk Read Failed in LBA mode: %x (%s) (DriveNumber: 0x%x SectorNumber: %I64u SectorCount: %u)\n",
221 RegsOut.b.ah, DiskGetErrorCodeString(RegsOut.b.ah),
222 DiskDrive->DaUa, SectorNumber, SectorCount);
223
224 return FALSE;
225}
226
227static
230 _In_ PPC98_DISK_DRIVE DiskDrive,
231 _In_ ULONG64 SectorNumber,
233 _Out_writes_bytes_all_(SectorCount * DiskDrive->Geometry.BytesPerSector) PVOID Buffer)
234{
235 UCHAR PhysicalSector;
236 UCHAR PhysicalHead;
237 ULONG PhysicalTrack;
238 GEOMETRY DriveGeometry;
239 ULONG NumberOfSectorsToRead;
240 REGS RegsIn, RegsOut;
241 ULONG RetryCount;
242
243 DriveGeometry = DiskDrive->Geometry;
244
245 while (SectorCount > 0)
246 {
247 /*
248 * Calculate the physical disk offsets.
249 * Note: DriveGeometry.SectorsPerTrack < 64
250 */
251 PhysicalSector = (UCHAR)(SectorNumber % DriveGeometry.SectorsPerTrack);
252 PhysicalHead = (UCHAR)((SectorNumber / DriveGeometry.SectorsPerTrack) % DriveGeometry.Heads);
253 PhysicalTrack = (ULONG)((SectorNumber / DriveGeometry.SectorsPerTrack) / DriveGeometry.Heads);
254
255 /* Floppy sectors value always start at 1 */
256 if (DiskDrive->Type == DRIVE_TYPE_FDD)
257 ++PhysicalSector;
258
259 /* Calculate how many sectors we need to read this round */
260 if (PhysicalSector > 1)
261 {
262 NumberOfSectorsToRead = min(SectorCount,
263 (DriveGeometry.SectorsPerTrack - (PhysicalSector - 1)));
264 }
265 else
266 {
267 NumberOfSectorsToRead = min(SectorCount, DriveGeometry.SectorsPerTrack);
268 }
269
270 /* Make sure the read is within the geometry boundaries */
271 if ((PhysicalHead >= DriveGeometry.Heads) ||
272 (PhysicalTrack >= DriveGeometry.Cylinders) ||
273 ((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.SectorsPerTrack + 1)) ||
274 (PhysicalSector > DriveGeometry.SectorsPerTrack))
275 {
276 DiskError("Disk read exceeds drive geometry limits.", 0);
277 return FALSE;
278 }
279
280 if (DiskDrive->Type == DRIVE_TYPE_FDD)
281 {
282 /* Int 1Bh AH=x6h
283 * DISK BIOS - Read data
284 *
285 * Call with:
286 * AL - drive number
287 * BX - bytes to read
288 * CH - sector length code
289 * CL - cylinder number
290 * DH - head number
291 * DL - sector number
292 * ES:BP -> buffer to read data into
293 *
294 * Return:
295 * CF - set on error, clear if successful
296 * AH - status
297 */
298 RegsIn.b.ah = 0x56; /* With SEEK, and use double-density format (MFM) */
299 RegsIn.w.bx = DriveGeometry.BytesPerSector * (UCHAR)NumberOfSectorsToRead;
300 RegsIn.b.cl = PhysicalTrack & 0xFFFF;
301 RegsIn.b.ch = BytesPerSectorToSectorLengthCode(DriveGeometry.BytesPerSector);
302 }
303 else
304 {
305 /* Int 1Bh AH=06h
306 * DISK BIOS - Read data
307 *
308 * Call with:
309 * AL - drive number
310 * BX - bytes to read
311 * CX - cylinder number
312 * DH - head number
313 * DL - sector number
314 * ES:BP -> buffer to read data into
315 *
316 * Return:
317 * CF - set on error, clear if successful
318 * AH - status
319 */
320 RegsIn.b.ah = 0x06;
321 RegsIn.w.bx = DriveGeometry.BytesPerSector * (UCHAR)NumberOfSectorsToRead;
322 RegsIn.w.cx = PhysicalTrack & 0xFFFF;
323 }
324 RegsIn.b.al = DiskDrive->DaUa;
325 RegsIn.b.dl = PhysicalSector;
326 RegsIn.b.dh = PhysicalHead;
327 RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4);
328 RegsIn.w.bp = ((ULONG_PTR)Buffer) & 0x0F;
329
330 /* Perform the read. Retry 3 times. */
331 for (RetryCount = 0; RetryCount < 3; ++RetryCount)
332 {
333 Int386(0x1B, &RegsIn, &RegsOut);
334
335 /* If it worked, or if it was a corrected ECC error
336 * and the data is still good, return success */
337 if (INT386_SUCCESS(RegsOut) || (RegsOut.b.ah == 0x08))
338 break;
339
340 /* It failed, do the next retry */
341 DiskResetController(DiskDrive);
342 }
343
344 /* If we retried 3 times then fail */
345 if (RetryCount >= 3)
346 {
347 DiskError("Disk Read Failed in CHS mode, after retrying 3 times", RegsOut.b.ah);
348 ERR("Disk Read Failed in CHS mode, after retrying 3 times: %x (%s) (DriveNumber: 0x%x SectorNumber: %I64u SectorCount: %u)\n",
349 RegsOut.b.ah, DiskGetErrorCodeString(RegsOut.b.ah),
350 DiskDrive->DaUa, SectorNumber, SectorCount);
351 return FALSE;
352 }
353
354 Buffer = (PVOID)((ULONG_PTR)Buffer + (NumberOfSectorsToRead * DriveGeometry.BytesPerSector));
355 SectorCount -= NumberOfSectorsToRead;
356 SectorNumber += NumberOfSectorsToRead;
357 }
358
359 return TRUE;
360}
361
362static
365 _Out_ PPC98_DISK_DRIVE DiskDrive,
366 _In_ UCHAR DaUa)
367{
368 REGS RegsIn, RegsOut;
369 UCHAR UnitAddress = DaUa & 0x0F;
370 USHORT DiskEquipment = *(PUCHAR)MEM_DISK_EQUIPS;
371 ULONG ScsiParameters = *(PULONG)(MEM_SCSI_TABLE + UnitAddress * sizeof(ULONG));
372
373 /* Hard drives */
374 if (DiskEquipment & (1 << UnitAddress))
375 {
376 /* Int 1Bh AH=84h
377 * DISK BIOS - Sense
378 *
379 * Call with:
380 * AL - drive number
381 *
382 * Return:
383 * BX - bytes per sector
384 * CX - cylinders number
385 * DH - heads number
386 * DL - sectors number
387 * CF - set on error, clear if successful
388 * AH - status
389 */
390 RegsIn.b.al = DaUa;
391 RegsIn.b.ah = 0x84;
392 Int386(0x1B, &RegsIn, &RegsOut);
393 if (!INT386_SUCCESS(RegsOut) || RegsOut.w.cx == 0)
394 return FALSE;
395
396 DiskDrive->Geometry.Cylinders = RegsOut.w.cx;
397 DiskDrive->Geometry.Heads = RegsOut.b.dh;
398 DiskDrive->Geometry.SectorsPerTrack = RegsOut.b.dl;
399 DiskDrive->Geometry.BytesPerSector = RegsOut.w.bx;
400 DiskDrive->Type = DRIVE_TYPE_HDD;
401 }
402 /* Other devices */
403 else if (ScsiParameters != 0)
404 {
405 UCHAR DeviceType = ScsiParameters & 0x1F;
406 switch (DeviceType)
407 {
408 case 0x05:
409 /* CD-ROM */
410 DiskDrive->Geometry.Cylinders = 0xFFFF;
411 DiskDrive->Geometry.Heads = 0xFFFF;
412 DiskDrive->Geometry.SectorsPerTrack = 0xFFFF;
413 DiskDrive->Geometry.BytesPerSector = 2048;
414
415 DiskDrive->Type = DRIVE_TYPE_CDROM;
416 DiskDrive->Flags = DRIVE_FLAGS_LBA | DRIVE_FLAGS_REMOVABLE;
417 break;
418
419 case 0x07:
420 /* Magneto-optical drive */
421 DiskDrive->Geometry.Cylinders = 0xFFFF;
422 DiskDrive->Geometry.Heads = 8;
423 DiskDrive->Geometry.SectorsPerTrack = 32;
424 DiskDrive->Geometry.BytesPerSector = 512;
425
426 DiskDrive->Type = DRIVE_TYPE_CDROM;
427 DiskDrive->Flags = DRIVE_FLAGS_LBA | DRIVE_FLAGS_REMOVABLE;
428 break;
429
430 default:
431 return FALSE;
432 }
433 }
434 else
435 {
436 return FALSE;
437 }
438
439 DiskDrive->Flags |= DRIVE_FLAGS_INITIALIZED;
440 DiskDrive->DaUa = DaUa;
441
442 DiskDrive->Geometry.Sectors = (ULONGLONG)DiskDrive->Geometry.Cylinders *
443 DiskDrive->Geometry.Heads *
444 DiskDrive->Geometry.SectorsPerTrack;
445
446 TRACE("InitScsiDrive(0x%x) returned:\n"
447 "Cylinders : 0x%x\n"
448 "Heads : 0x%x\n"
449 "Sects/Track: 0x%x\n"
450 "Total Sects: 0x%llx\n"
451 "Bytes/Sect : 0x%x\n",
452 DaUa,
453 DiskDrive->Geometry.Cylinders,
454 DiskDrive->Geometry.Heads,
455 DiskDrive->Geometry.SectorsPerTrack,
456 DiskDrive->Geometry.Sectors,
457 DiskDrive->Geometry.BytesPerSector);
458
459 return TRUE;
460}
461
462static
465 _Out_ PPC98_DISK_DRIVE DiskDrive,
466 _In_ UCHAR DaUa)
467{
468 REGS RegsIn, RegsOut;
469 ULONG BytesPerSector;
471
472 /* Int 1Bh AH=4Ah
473 * DISK BIOS - Read ID
474 *
475 * Call with:
476 * AL - drive number
477 *
478 * Return:
479 * CH - sector size
480 * CL - cylinder
481 * DH - head
482 * DL - sector
483 * CF - set on error, clear if successful
484 * AH - status
485 */
486 RegsIn.b.ah = 0x4A;
487 RegsIn.b.al = DaUa;
488 Int386(0x1B, &RegsIn, &RegsOut);
489 if (!INT386_SUCCESS(RegsOut))
490 return FALSE;
491
492 /* There is no way to obtain floppy disk geometry in BIOS */
493 DeviceAddress = DaUa & 0xF0;
494 BytesPerSector = 128 << RegsOut.b.ch;
495 switch (BytesPerSector)
496 {
497 case 256:
498 if (DeviceAddress == 0x50)
499 {
500 /* 320 kB 2DD */
501 DiskDrive->Geometry.Cylinders = 80;
502 DiskDrive->Geometry.Heads = 2;
503 DiskDrive->Geometry.SectorsPerTrack = 16;
504 }
505 else
506 {
507 /* 1 MB 2HD */
508 DiskDrive->Geometry.Cylinders = 77;
509 DiskDrive->Geometry.Heads = 2;
510 DiskDrive->Geometry.SectorsPerTrack = 26;
511 }
512 break;
513
514 case 512:
515 if (DeviceAddress == 0x30 || DeviceAddress == 0xB0)
516 {
517 /* 1.44 MB 2HD */
518 DiskDrive->Geometry.Cylinders = 80;
519 DiskDrive->Geometry.Heads = 2;
520 DiskDrive->Geometry.SectorsPerTrack = 18;
521 }
522 else if (DeviceAddress == 0x70 || DeviceAddress == 0xF0)
523 {
524 /* 720/640 kB 2DD */
525 DiskDrive->Geometry.Cylinders = 80;
526 DiskDrive->Geometry.Heads = 2;
527 DiskDrive->Geometry.SectorsPerTrack = 8;
528 }
529 else
530 {
531 /* 1.2 MB 2HC */
532 DiskDrive->Geometry.Cylinders = 80;
533 DiskDrive->Geometry.Heads = 2;
534 DiskDrive->Geometry.SectorsPerTrack = 15;
535 }
536 break;
537
538 case 1024:
539 /* 1.25 MB 2HD */
540 DiskDrive->Geometry.Cylinders = 77;
541 DiskDrive->Geometry.Heads = 2;
542 DiskDrive->Geometry.SectorsPerTrack = 8;
543 break;
544
545 default:
546 return FALSE;
547 }
548
549 DiskDrive->Geometry.BytesPerSector = BytesPerSector;
550 DiskDrive->Geometry.Sectors = (ULONGLONG)DiskDrive->Geometry.Cylinders *
551 DiskDrive->Geometry.Heads *
552 DiskDrive->Geometry.SectorsPerTrack;
553
554 DiskDrive->DaUa = DaUa;
555 DiskDrive->Type = DRIVE_TYPE_FDD;
557
558 TRACE("InitFloppyDrive(0x%x) returned:\n"
559 "Cylinders : 0x%x\n"
560 "Heads : 0x%x\n"
561 "Sects/Track: 0x%x\n"
562 "Total Sects: 0x%llx\n"
563 "Bytes/Sect : 0x%x\n",
564 DaUa,
565 DiskDrive->Geometry.Cylinders,
566 DiskDrive->Geometry.Heads,
567 DiskDrive->Geometry.SectorsPerTrack,
568 DiskDrive->Geometry.Sectors,
569 DiskDrive->Geometry.BytesPerSector);
570
571 return TRUE;
572}
573
574static
577 _Out_ PPC98_DISK_DRIVE DiskDrive,
578 _In_ UCHAR AtaUnitNumber)
579{
580 PDEVICE_UNIT DeviceUnit = AtaGetDevice(AtaUnitNumber);
581
582 if (!DeviceUnit)
583 return FALSE;
584
585 DiskDrive->Geometry.Cylinders = DeviceUnit->Cylinders;
586 DiskDrive->Geometry.Heads = DeviceUnit->Heads;
587 DiskDrive->Geometry.SectorsPerTrack = DeviceUnit->SectorsPerTrack;
588 DiskDrive->Geometry.BytesPerSector = DeviceUnit->SectorSize;
589 DiskDrive->Geometry.Sectors = DeviceUnit->TotalSectors;
590
591 DiskDrive->DaUa = 0xFF; // Invalid
592 DiskDrive->AtaUnitNumber = AtaUnitNumber;
593 DiskDrive->Flags = DRIVE_FLAGS_IDE | DRIVE_FLAGS_INITIALIZED;
594
595 if (DeviceUnit->Flags & ATA_DEVICE_LBA)
596 DiskDrive->Flags |= DRIVE_FLAGS_LBA;
597
598 if (DeviceUnit->Flags & ATA_DEVICE_ATAPI)
599 {
600 DiskDrive->Type = DRIVE_TYPE_CDROM;
601 DiskDrive->Flags |= DRIVE_FLAGS_REMOVABLE;
602 }
603 else
604 {
605 DiskDrive->Type = DRIVE_TYPE_HDD;
606 }
607
608 TRACE("InitIdeDrive(0x%x) returned:\n"
609 "Cylinders : 0x%x\n"
610 "Heads : 0x%x\n"
611 "Sects/Track: 0x%x\n"
612 "Total Sects: 0x%llx\n"
613 "Bytes/Sect : 0x%x\n",
614 AtaUnitNumber,
615 DiskDrive->Geometry.Cylinders,
616 DiskDrive->Geometry.Heads,
617 DiskDrive->Geometry.SectorsPerTrack,
618 DiskDrive->Geometry.Sectors,
619 DiskDrive->Geometry.BytesPerSector);
620 return TRUE;
621}
622
625{
626 USHORT DiskEquipment = *(PUSHORT)MEM_DISK_EQUIP & ~(*(PUCHAR)MEM_RDISK_EQUIP);
627 PPC98_DISK_DRIVE DiskDrive;
628 UCHAR BiosFloppyDriveNumber, BiosHardDriveDriveNumber, IdeDetectedCount;
629 ULONG i;
630
631 TRACE("Pc98InitializeBootDevices()\n");
632
634
635 /*
636 * We emulate the standard PC BIOS drive numbers here. Map DA/UA to a drive number, i.e.
637 * 0x90 -> 0x30
638 * 0x80 -> 0x80
639 * 0xA0 -> 0x81, etc.
640 */
641 BiosFloppyDriveNumber = 0x30;
642 BiosHardDriveDriveNumber = 0x80;
643
644 /* Map floppies */
645 for (i = 0; i < 4; i++)
646 {
647 DiskDrive = &Pc98DiskDrive[BiosFloppyDriveNumber];
648 if (FIRSTBYTE(DiskEquipment) & (1 << i))
649 {
650 if (InitFloppyDrive(DiskDrive, 0x30 + i) || InitFloppyDrive(DiskDrive, 0xB0 + i) ||
651 InitFloppyDrive(DiskDrive, 0x90 + i) || InitFloppyDrive(DiskDrive, 0x10 + i))
652 ++BiosFloppyDriveNumber;
653 }
654 }
655 for (i = 0; i < 4; i++)
656 {
657 DiskDrive = &Pc98DiskDrive[BiosFloppyDriveNumber];
658 if (FIRSTBYTE(DiskEquipment) & (16 << i))
659 {
660 if (InitFloppyDrive(DiskDrive, 0x50 + i))
661 ++BiosFloppyDriveNumber;
662 }
663 }
664 for (i = 0; i < 4; i++)
665 {
666 DiskDrive = &Pc98DiskDrive[BiosFloppyDriveNumber];
667 if (SECONDBYTE(DiskEquipment) & (16 << i))
668 {
669 if (InitFloppyDrive(DiskDrive, 0x70 + i) || InitFloppyDrive(DiskDrive, 0xF0 + i))
670 ++BiosFloppyDriveNumber;
671 }
672 }
673
674 /*
675 * Map IDE drives. We provide our own IDE boot support because of IDE BIOS
676 * that cannot boot from a CD-ROM and has LBA limitations.
677 */
678 AtaInit(&IdeDetectedCount);
679 for (i = 0; i < IdeDetectedCount; i++)
680 {
681 DiskDrive = &Pc98DiskDrive[BiosHardDriveDriveNumber];
682 if (InitIdeDrive(DiskDrive, i))
683 ++BiosHardDriveDriveNumber;
684 }
685
686 /* Map SCSI drives */
687 for (i = 0; i < 7; i++)
688 {
689 DiskDrive = &Pc98DiskDrive[BiosHardDriveDriveNumber];
690 if (InitScsiDrive(DiskDrive, 0xA0 + i) || InitScsiDrive(DiskDrive, 0x20 + i))
691 ++BiosHardDriveDriveNumber;
692 }
693
694 // Ugly HACK: Force ISO boot
695 // FIXME: Fill ARC disk blocks completely
696 // to allow usage of CD-ROM root path (See floppy_pc98.ini).
697 for (i = 0x80; i < RTL_NUMBER_OF(Pc98DiskDrive); i++)
698 {
699 DiskDrive = &Pc98DiskDrive[i];
700
701 if ((DiskDrive->Flags & DRIVE_FLAGS_INITIALIZED) &&
702 (DiskDrive->Flags & DRIVE_FLAGS_IDE) &&
703 (DiskDrive->Type == DRIVE_TYPE_CDROM))
704 {
706 FrldrBootPartition = 0xFF;
707 break;
708 }
709 }
710
711 /* Call PC version */
713}
714
717 _In_ UCHAR DriveNumber,
718 _In_ ULONGLONG SectorNumber,
721{
722 PPC98_DISK_DRIVE DiskDrive;
723
724 TRACE("Pc98DiskReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %I64u SectorCount: %u Buffer: 0x%x\n",
725 DriveNumber, SectorNumber, SectorCount, Buffer);
726
727 /* 16-bit BIOS addressing limitation */
728 ASSERT(((ULONG_PTR)Buffer) <= 0xFFFFF);
729
730 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber);
731 if (!DiskDrive)
732 return FALSE;
733
734 if (DiskDrive->Flags & DRIVE_FLAGS_IDE)
735 {
737 SectorNumber,
739 Buffer);
740 }
741 else if (DiskDrive->Flags & DRIVE_FLAGS_LBA)
742 {
743 /* LBA is easy, nothing to calculate. Just do the read. */
744 TRACE("--> Using LBA\n");
745 return Pc98DiskReadLogicalSectorsLBA(DiskDrive, SectorNumber, SectorCount, Buffer);
746 }
747 else
748 {
749 /* LBA is not supported, default to CHS */
750 TRACE("--> Using CHS\n");
751 return Pc98DiskReadLogicalSectorsCHS(DiskDrive, SectorNumber, SectorCount, Buffer);
752 }
753}
754
757 _In_ UCHAR DriveNumber,
758 _Out_ PGEOMETRY Geometry)
759{
760 PPC98_DISK_DRIVE DiskDrive;
761
762 TRACE("Pc98DiskGetDriveGeometry(0x%x)\n", DriveNumber);
763
764 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber);
765 if (!DiskDrive)
766 return FALSE;
767
768 *Geometry = DiskDrive->Geometry;
769
770 return TRUE;
771}
772
773ULONG
775 _In_ UCHAR DriveNumber)
776{
777 PPC98_DISK_DRIVE DiskDrive;
778
779 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber);
780 if (!DiskDrive)
781 return 1; // Unknown count.
782
783 /*
784 * If LBA is supported then the block size will be 64 sectors (32k).
785 * If not then the block size is the size of one track.
786 */
787 if (DiskDrive->Flags & DRIVE_FLAGS_LBA)
788 return 64;
789 else
790 return DiskDrive->Geometry.SectorsPerTrack;
791}
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
unsigned char BOOLEAN
Definition: actypes.h:127
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
VOID DiskError(_In_ PCSTR ErrorString, _In_ ULONG ErrorCode)
Definition: disk.c:48
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ULONG_PTR
Definition: config.h:101
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_In_ PUSB_DEVICE_HANDLE _Out_ PUSHORT DeviceAddress
Definition: hubbusif.h:360
BOOLEAN PcInitializeBootDevices(VOID)
Definition: hwdisk.c:427
PDEVICE_UNIT AtaGetDevice(_In_ UCHAR UnitNumber)
Definition: hwide.c:1270
BOOLEAN AtaInit(_Out_ PUCHAR DetectedCount)
Definition: hwide.c:1279
BOOLEAN AtaReadLogicalSectors(_In_ PDEVICE_UNIT DeviceUnit, _In_ ULONG64 SectorNumber, _In_ ULONG SectorCount, _Out_writes_bytes_all_(SectorCount *DeviceUnit->SectorSize) PVOID Buffer)
Definition: hwide.c:1230
#define ATA_DEVICE_LBA
Definition: hwide.h:31
#define ATA_DEVICE_ATAPI
Definition: hwide.h:30
#define MEM_RDISK_EQUIP
Definition: machpc98.h:33
#define MEM_DISK_EQUIP
Definition: machpc98.h:41
#define MEM_SCSI_TABLE
Definition: machpc98.h:24
#define DRIVE_FLAGS_IDE
Definition: machpc98.h:122
#define DRIVE_TYPE_CDROM
Definition: machpc98.h:117
#define DRIVE_FLAGS_REMOVABLE
Definition: machpc98.h:124
#define DRIVE_TYPE_HDD
Definition: machpc98.h:116
#define MEM_DISK_EQUIPS
Definition: machpc98.h:30
#define DRIVE_FLAGS_INITIALIZED
Definition: machpc98.h:125
#define DRIVE_TYPE_FDD
Definition: machpc98.h:118
#define DRIVE_FLAGS_LBA
Definition: machpc98.h:123
DeviceType
Definition: mmdrv.h:42
#define ASSERT(a)
Definition: mode.c:44
unsigned __int64 ULONG64
Definition: imports.h:198
#define min(a, b)
Definition: monoChain.cc:55
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4436
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _Out_writes_bytes_all_(s)
Definition: no_sal2.h:194
ULONG SectorCount
Definition: part_brfr.c:22
static BOOLEAN InitScsiDrive(_Out_ PPC98_DISK_DRIVE DiskDrive, _In_ UCHAR DaUa)
Definition: pc98disk.c:364
ULONG Pc98DiskGetCacheableBlockCount(_In_ UCHAR DriveNumber)
Definition: pc98disk.c:774
PCSTR DiskGetErrorCodeString(_In_ ULONG ErrorCode)
Definition: pc98disk.c:28
static BOOLEAN InitFloppyDrive(_Out_ PPC98_DISK_DRIVE DiskDrive, _In_ UCHAR DaUa)
Definition: pc98disk.c:464
static BOOLEAN Pc98DiskReadLogicalSectorsCHS(_In_ PPC98_DISK_DRIVE DiskDrive, _In_ ULONG64 SectorNumber, _In_ ULONG SectorCount, _Out_writes_bytes_all_(SectorCount *DiskDrive->Geometry.BytesPerSector) PVOID Buffer)
Definition: pc98disk.c:229
static PC98_DISK_DRIVE Pc98DiskDrive[MAX_DRIVES]
Definition: pc98disk.c:22
static BOOLEAN Pc98DiskReadLogicalSectorsLBA(_In_ PPC98_DISK_DRIVE DiskDrive, _In_ ULONG64 SectorNumber, _In_ ULONG SectorCount, _Out_writes_bytes_all_(SectorCount *DiskDrive->Geometry.BytesPerSector) PVOID Buffer)
Definition: pc98disk.c:172
BOOLEAN Pc98DiskGetDriveGeometry(_In_ UCHAR DriveNumber, _Out_ PGEOMETRY Geometry)
Definition: pc98disk.c:756
BOOLEAN Pc98InitializeBootDevices(VOID)
Definition: pc98disk.c:624
BOOLEAN Pc98DiskReadLogicalSectors(_In_ UCHAR DriveNumber, _In_ ULONGLONG SectorNumber, _In_ ULONG SectorCount, _Out_ PVOID Buffer)
Definition: pc98disk.c:716
CONFIGURATION_TYPE DiskGetConfigType(_In_ UCHAR DriveNumber)
Definition: pc98disk.c:131
static UCHAR BytesPerSectorToSectorLengthCode(_In_ ULONG BytesPerSector)
Definition: pc98disk.c:150
#define MAX_DRIVES
Definition: pc98disk.c:19
static BOOLEAN DiskResetController(_In_ PPC98_DISK_DRIVE DiskDrive)
Definition: pc98disk.c:66
static BOOLEAN InitIdeDrive(_Out_ PPC98_DISK_DRIVE DiskDrive, _In_ UCHAR AtaUnitNumber)
Definition: pc98disk.c:576
PPC98_DISK_DRIVE Pc98DiskDriveNumberToDrive(_In_ UCHAR DriveNumber)
Definition: pc98disk.c:113
#define INT386_SUCCESS(regs)
Definition: pcbios.h:181
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned short USHORT
Definition: pedump.c:61
@ DiskPeripheral
Definition: arc.h:138
@ FloppyDiskPeripheral
Definition: arc.h:139
@ CdromController
Definition: arc.h:128
enum _CONFIGURATION_TYPE CONFIGURATION_TYPE
#define TRACE(s)
Definition: solgame.cpp:4
unsigned char ch
Definition: pcbios.h:140
unsigned char dl
Definition: pcbios.h:142
unsigned char cl
Definition: pcbios.h:139
unsigned char al
Definition: pcbios.h:133
unsigned char ah
Definition: pcbios.h:134
unsigned char dh
Definition: pcbios.h:143
unsigned short bp
Definition: pcbios.h:120
unsigned short es
Definition: pcbios.h:123
unsigned short cx
Definition: pcbios.h:115
unsigned short dx
Definition: pcbios.h:116
unsigned short bx
Definition: pcbios.h:114
Data structure for the ATA device.
Definition: hwide.h:12
ULONG Cylinders
Definition: hwide.h:14
ULONG SectorSize
Definition: hwide.h:23
ULONG SectorsPerTrack
Definition: hwide.h:20
ULONG64 TotalSectors
Definition: hwide.h:26
ULONG Flags
Definition: hwide.h:29
ULONG Heads
Definition: hwide.h:17
Definition: disk.h:24
ULONG BytesPerSector
Number of bytes per sector.
Definition: disk.h:28
ULONG Cylinders
Number of cylinders on the disk.
Definition: disk.h:25
ULONG SectorsPerTrack
Number of sectors per track.
Definition: disk.h:27
ULONG Heads
Number of heads on the disk.
Definition: disk.h:26
UCHAR AtaUnitNumber
Definition: machpc98.h:112
GEOMETRY Geometry
Definition: machpc98.h:106
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char UCHAR
Definition: typedefs.h:53
void * PVOID
Definition: typedefs.h:50
uint16_t * PUSHORT
Definition: typedefs.h:56
const char * PCSTR
Definition: typedefs.h:52
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
UCHAR FrldrBootDrive
Definition: uefidisk.c:57
ULONG FrldrBootPartition
Definition: uefidisk.c:58
Definition: pcbios.h:161
BYTEREGS b
Definition: pcbios.h:165
WORDREGS w
Definition: pcbios.h:164
#define SECONDBYTE(VALUE)
Definition: rtlfuncs.h:807
#define FIRSTBYTE(VALUE)
Definition: rtlfuncs.h:806