ReactOS 0.4.16-dev-88-ga65b6ae
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
26static LONG lReportError = 0; /* >= 0: display errors; < 0: hide errors */
27
28LONG
30{
31 /* Set the reference count */
32 if (bShowError)
34 else
36 return lReportError;
37}
38
39static PCSTR
41{
42 switch (ErrorCode & 0xF0)
43 {
44 case 0x00: return "No error";
45 case 0x10: return "Drive write protection error";
46 case 0x20: return "DMA access across 64 kB boundary";
47 case 0x30: return "End of cylinder";
48 case 0x40: return "The drive name is invalid or the device have low health";
49 case 0x50: return "Time out, data not written";
50 case 0x60: return "Time out, drive not ready";
51 case 0x70:
52 if (ErrorCode == 0x78)
53 return "Illegal disk address";
54 else
55 return "Drive write protection error";
56 case 0x80: return "Undefined error";
57 case 0x90: return "Time out error";
58 case 0xA0: return "CRC error in the ID section";
59 case 0xB0: return "CRC error in the DATA section";
60 case 0xC0:
61 if (ErrorCode == 0xC8)
62 return "Seek failure";
63 else
64 return "No data (Sector not found)";
65 case 0xD0: return "Bad cylinder";
66 case 0xE0: return "No ID address mark was found";
67 case 0xF0: return "No DATA address mark was found";
68
69 default: return "Unknown error code";
70 }
71}
72
73static VOID
75{
76 CHAR ErrorCodeString[200];
77
78 if (lReportError < 0)
79 return;
80
81 RtlStringCbPrintfA(ErrorCodeString, sizeof(ErrorCodeString), "%s\n\nError Code: 0x%lx\nError: %s",
83
84 ERR("%s\n", ErrorCodeString);
85
86 UiMessageBox(ErrorCodeString);
87}
88
89/* FUNCTIONS ******************************************************************/
90
92{
93 REGS Regs;
94
95 if (DiskDrive->Type & DRIVE_FDD)
96 {
97 /* Int 1Bh AH=07h
98 * DISK BIOS - Recalibrate
99 *
100 * Call with:
101 * AL - drive number
102 *
103 * Return:
104 * CF - set on error, clear if successful
105 * AH - status
106 */
107 Regs.b.ah = 0x07;
108 }
109 else if (DiskDrive->Type != (DRIVE_IDE | DRIVE_CDROM))
110 {
111 /* Int 1Bh AH=03h
112 * DISK BIOS - Initialize
113 *
114 * Call with:
115 * AL - drive number
116 *
117 * Return:
118 * CF - set on error, clear if successful
119 * AH - status
120 */
121 Regs.b.ah = 0x03;
122 }
123 else
124 {
125 return FALSE;
126 }
127
128 WARN("DiskResetController(0x%x) DISK OPERATION FAILED -- RESETTING CONTROLLER\n", DiskDrive->DaUa);
129
130 Regs.b.al = DiskDrive->DaUa;
131 Int386(0x1B, &Regs, &Regs);
132 return INT386_SUCCESS(Regs);
133}
134
136{
137 AtaFree();
138}
139
142{
143 PPC98_DISK_DRIVE DiskDrive;
144
145 ASSERT((0 <= DriveNumber) && (DriveNumber < RTL_NUMBER_OF(Pc98DiskDrive)));
146
147 /* Retrieve a slot */
148 DiskDrive = &Pc98DiskDrive[DriveNumber];
149
150 /* The pre-initialization of the BIOS disks was already done in Pc98InitializeBootDevices() */
151 if (DiskDrive->Initialized)
152 return DiskDrive;
153 else
154 return NULL;
155}
156
157static inline
158UCHAR
160{
161 switch (BytesPerSector)
162 {
163 case 128:
164 return 0;
165 case 256:
166 return 1;
167 case 512:
168 return 2;
169 case 1024:
170 return 3;
171 case 2048:
172 return 4;
173 default:
174 return 0;
175 }
176}
177
178static BOOLEAN
180 IN PPC98_DISK_DRIVE DiskDrive,
181 IN ULONGLONG SectorNumber,
184{
185 REGS RegsIn, RegsOut;
186 ULONG RetryCount;
187
188 if (DiskDrive->Type & DRIVE_IDE && DiskDrive->Type & DRIVE_CDROM)
189 {
190 return AtaAtapiReadLogicalSectorsLBA(AtaGetDevice(DiskDrive->IdeUnitNumber), SectorNumber, SectorCount, Buffer);
191 }
192 else
193 {
194 /* Int 1Bh AH=06h
195 * DISK BIOS - Read data
196 *
197 * Call with:
198 * AL - drive number
199 * BX - bytes to read
200 * CX - cylinder number
201 * DH - head number
202 * DL - sector number
203 * ES:BP -> buffer to read data into
204 *
205 * Return:
206 * CF - set on error, clear if successful
207 * AH - status
208 */
209 RegsIn.b.al = DiskDrive->DaUa;
210 RegsIn.b.ah = 0x06;
211 RegsIn.w.bx = DiskDrive->Geometry.BytesPerSector * SectorCount;
212 RegsIn.w.cx = SectorNumber & 0xFFFF;
213 RegsIn.w.dx = (SectorNumber >> 16) & 0xFFFF;
214 RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4);
215 RegsIn.w.bp = ((ULONG_PTR)Buffer) & 0x0F;
216
217 /* Retry 3 times */
218 for (RetryCount = 0; RetryCount < 3; RetryCount++)
219 {
220 Int386(0x1B, &RegsIn, &RegsOut);
221
222 /* If it worked return TRUE */
223 if (INT386_SUCCESS(RegsOut))
224 {
225 return TRUE;
226 }
227 /* If it was a corrected ECC error then the data is still good */
228 else if (RegsOut.b.ah == 0x08)
229 {
230 return TRUE;
231 }
232 /* If it failed the do the next retry */
233 else
234 {
235 DiskResetController(DiskDrive);
236 continue;
237 }
238 }
239 }
240
241 /* If we get here then the read failed */
242 DiskError("Disk Read Failed in LBA mode", RegsOut.b.ah);
243 ERR("Disk Read Failed in LBA mode: %x (%s) (DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d)\n",
244 RegsOut.b.ah, DiskGetErrorCodeString(RegsOut.b.ah),
245 DiskDrive->DaUa, SectorNumber, SectorCount);
246
247 return FALSE;
248}
249
250static BOOLEAN
252 IN PPC98_DISK_DRIVE DiskDrive,
253 IN ULONGLONG SectorNumber,
256{
257 UCHAR PhysicalSector;
258 UCHAR PhysicalHead;
259 ULONG PhysicalTrack;
260 GEOMETRY DriveGeometry;
261 ULONG NumberOfSectorsToRead;
262 REGS RegsIn, RegsOut;
263 ULONG RetryCount;
264
265 DriveGeometry = DiskDrive->Geometry;
266
267 while (SectorCount > 0)
268 {
269 /*
270 * Calculate the physical disk offsets.
271 * Note: DriveGeometry.SectorsPerTrack < 64
272 */
273 PhysicalSector = (UCHAR)(SectorNumber % DriveGeometry.SectorsPerTrack);
274 PhysicalHead = (UCHAR)((SectorNumber / DriveGeometry.SectorsPerTrack) % DriveGeometry.Heads);
275 PhysicalTrack = (ULONG)((SectorNumber / DriveGeometry.SectorsPerTrack) / DriveGeometry.Heads);
276
277 /* Floppy sectors value always start at 1 */
278 if (DiskDrive->Type & DRIVE_FDD)
279 ++PhysicalSector;
280
281 /* Calculate how many sectors we need to read this round */
282 if (PhysicalSector > 1)
283 {
284 NumberOfSectorsToRead = min(SectorCount,
285 (DriveGeometry.SectorsPerTrack - (PhysicalSector - 1)));
286 }
287 else
288 {
289 NumberOfSectorsToRead = min(SectorCount, DriveGeometry.SectorsPerTrack);
290 }
291
292 /* Make sure the read is within the geometry boundaries */
293 if ((PhysicalHead >= DriveGeometry.Heads) ||
294 (PhysicalTrack >= DriveGeometry.Cylinders) ||
295 ((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.SectorsPerTrack + 1)) ||
296 (PhysicalSector > DriveGeometry.SectorsPerTrack))
297 {
298 DiskError("Disk read exceeds drive geometry limits.", 0);
299 return FALSE;
300 }
301
302 if (DiskDrive->Type & DRIVE_FDD)
303 {
304 /* Int 1Bh AH=x6h
305 * DISK BIOS - Read data
306 *
307 * Call with:
308 * AL - drive number
309 * BX - bytes to read
310 * CH - sector length code
311 * CL - 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.al = DiskDrive->DaUa;
321 RegsIn.b.ah = 0x56; /* With SEEK, and use double-density format (MFM) */
322 RegsIn.w.bx = DriveGeometry.BytesPerSector * (UCHAR)NumberOfSectorsToRead;
323 RegsIn.b.cl = PhysicalTrack & 0xFFFF;
324 RegsIn.b.ch = BytesPerSectorToSectorLengthCode(DriveGeometry.BytesPerSector);
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 else
331 {
332 /* Int 1Bh AH=06h
333 * DISK BIOS - Read data
334 *
335 * Call with:
336 * AL - drive number
337 * BX - bytes to read
338 * CX - cylinder number
339 * DH - head number
340 * DL - sector number
341 * ES:BP -> buffer to read data into
342 *
343 * Return:
344 * CF - set on error, clear if successful
345 * AH - status
346 */
347 RegsIn.b.al = DiskDrive->DaUa;
348 RegsIn.b.ah = 0x06;
349 RegsIn.w.bx = DriveGeometry.BytesPerSector * (UCHAR)NumberOfSectorsToRead;
350 RegsIn.w.cx = PhysicalTrack & 0xFFFF;
351 RegsIn.b.dl = PhysicalSector;
352 RegsIn.b.dh = PhysicalHead;
353 RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4);
354 RegsIn.w.bp = ((ULONG_PTR)Buffer) & 0x0F;
355 }
356
357 /* Perform the read. Retry 3 times. */
358 for (RetryCount = 0; RetryCount < 3; RetryCount++)
359 {
360 Int386(0x1B, &RegsIn, &RegsOut);
361
362 /* If it worked break out */
363 if (INT386_SUCCESS(RegsOut))
364 {
365 break;
366 }
367 /* If it was a corrected ECC error then the data is still good */
368 else if (RegsOut.b.ah == 0x08)
369 {
370 break;
371 }
372 /* If it failed then do the next retry */
373 else
374 {
375 DiskResetController(DiskDrive);
376 continue;
377 }
378 }
379
380 /* If we retried 3 times then fail */
381 if (RetryCount >= 3)
382 {
383 DiskError("Disk Read Failed in CHS mode, after retrying 3 times", RegsOut.b.ah);
384 ERR("Disk Read Failed in CHS mode, after retrying 3 times: %x (%s) (DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d)\n",
385 RegsOut.b.ah, DiskGetErrorCodeString(RegsOut.b.ah),
386 DiskDrive->DaUa, SectorNumber, SectorCount);
387 return FALSE;
388 }
389
390 Buffer = (PVOID)((ULONG_PTR)Buffer + (NumberOfSectorsToRead * DriveGeometry.BytesPerSector));
391 SectorCount -= NumberOfSectorsToRead;
392 SectorNumber += NumberOfSectorsToRead;
393 }
394
395 return TRUE;
396}
397
398static BOOLEAN
400 IN UCHAR DaUa,
401 IN OUT PPC98_DISK_DRIVE DiskDrive)
402{
403 REGS RegsIn, RegsOut;
404 UCHAR UnitAddress = DaUa & 0x0F;
405 USHORT DiskEquipment = *(PUCHAR)MEM_DISK_EQUIPS;
406 ULONG ScsiParameters = *(PULONG)(MEM_SCSI_TABLE + UnitAddress * sizeof(ULONG));
408
409 /* Hard drives */
410 if (DiskEquipment & (1 << UnitAddress))
411 {
412 /* Int 1Bh AH=84h
413 * DISK BIOS - Sense
414 *
415 * Call with:
416 * AL - drive number
417 *
418 * Return:
419 * BX - bytes per sector
420 * CX - cylinders number
421 * DH - heads number
422 * DL - sectors number
423 * CF - set on error, clear if successful
424 * AH - status
425 */
426 RegsIn.b.al = DaUa;
427 RegsIn.b.ah = 0x84;
428 Int386(0x1B, &RegsIn, &RegsOut);
429 if (!INT386_SUCCESS(RegsOut) || RegsOut.w.cx == 0)
430 {
431 DiskDrive->Initialized = FALSE;
432 return FALSE;
433 }
434
435 DiskDrive->Geometry.Cylinders = RegsOut.w.cx;
436 DiskDrive->Geometry.Heads = RegsOut.b.dh;
437 DiskDrive->Geometry.SectorsPerTrack = RegsOut.b.dl;
438 DiskDrive->Geometry.BytesPerSector = RegsOut.w.bx;
439 DiskDrive->LBASupported = FALSE;
440 DiskDrive->IsRemovable = FALSE;
441 }
442 /* Other devices */
443 else if (ScsiParameters)
444 {
445 DeviceType = ScsiParameters & 0x1F;
446 switch (DeviceType)
447 {
448 case 0x05:
449 /* CD-ROM */
450 DiskDrive->Geometry.Cylinders = 0xFFFF;
451 DiskDrive->Geometry.Heads = 0xFFFF;
452 DiskDrive->Geometry.SectorsPerTrack = 0xFFFF;
453 DiskDrive->Geometry.BytesPerSector = 2048;
454 DiskDrive->Type = DRIVE_CDROM;
455 DiskDrive->LBASupported = TRUE;
456 DiskDrive->IsRemovable = TRUE;
457 break;
458
459 case 0x07:
460 /* Magneto-optical drive */
461 DiskDrive->Geometry.Cylinders = 0xFFFF;
462 DiskDrive->Geometry.Heads = 8;
463 DiskDrive->Geometry.SectorsPerTrack = 32;
464 DiskDrive->Geometry.BytesPerSector = 512;
465 DiskDrive->Type = DRIVE_MO;
466 DiskDrive->LBASupported = TRUE;
467 DiskDrive->IsRemovable = TRUE;
468 break;
469
470 default:
471 DiskDrive->Initialized = FALSE;
472 return FALSE;
473 }
474 }
475 else
476 {
477 DiskDrive->Initialized = FALSE;
478 return FALSE;
479 }
480
481 DiskDrive->Geometry.Sectors = (ULONGLONG)DiskDrive->Geometry.Cylinders *
482 DiskDrive->Geometry.Heads *
483 DiskDrive->Geometry.SectorsPerTrack;
484
485 DiskDrive->DaUa = DaUa;
486 DiskDrive->Type |= DRIVE_SCSI;
487 DiskDrive->Initialized = TRUE;
488
489 TRACE("InitScsiDrive(0x%x) returned:\n"
490 "Cylinders : 0x%x\n"
491 "Heads : 0x%x\n"
492 "Sects/Track: 0x%x\n"
493 "Bytes/Sect : 0x%x\n",
494 DaUa,
495 DiskDrive->Geometry.Cylinders,
496 DiskDrive->Geometry.Heads,
497 DiskDrive->Geometry.SectorsPerTrack,
498 DiskDrive->Geometry.BytesPerSector);
499
500 return TRUE;
501}
502
503static BOOLEAN
505 IN UCHAR UnitNumber,
506 IN OUT PPC98_DISK_DRIVE DiskDrive)
507{
508 PDEVICE_UNIT DeviceUnit = AtaGetDevice(UnitNumber);
509
510 /* We work directly only with ATAPI drives because BIOS has ATA support */
511 if (DeviceUnit && DeviceUnit->Flags & ATA_DEVICE_ATAPI)
512 {
513 DiskDrive->Geometry.Cylinders = DeviceUnit->Cylinders;
514 DiskDrive->Geometry.Heads = DeviceUnit->Heads;
515 DiskDrive->Geometry.SectorsPerTrack = DeviceUnit->Sectors;
516 DiskDrive->Geometry.BytesPerSector = DeviceUnit->SectorSize;
517 DiskDrive->Geometry.Sectors = DeviceUnit->TotalSectors;
518
519 DiskDrive->DaUa = 0xFF;
520 DiskDrive->IdeUnitNumber = UnitNumber;
521 DiskDrive->Type = DRIVE_IDE | DRIVE_CDROM;
522 DiskDrive->LBASupported = TRUE;
523 DiskDrive->IsRemovable = TRUE;
524 DiskDrive->Initialized = TRUE;
525
526 TRACE("InitIdeDrive(0x%x) returned:\n"
527 "Cylinders : 0x%x\n"
528 "Heads : 0x%x\n"
529 "Sects/Track: 0x%x\n"
530 "Bytes/Sect : 0x%x\n",
531 UnitNumber,
532 DiskDrive->Geometry.Cylinders,
533 DiskDrive->Geometry.Heads,
534 DiskDrive->Geometry.SectorsPerTrack,
535 DiskDrive->Geometry.BytesPerSector);
536
537 return TRUE;
538 }
539
540 DiskDrive->Initialized = FALSE;
541 return FALSE;
542}
543
544static BOOLEAN
546 IN UCHAR DaUa,
547 IN OUT PPC98_DISK_DRIVE DiskDrive)
548{
549 REGS RegsIn, RegsOut;
550
551 /* Int 1Bh AH=8Eh
552 * DISK BIOS - Set half-height operation mode
553 *
554 * Call with:
555 * AL - drive number
556 */
557 RegsIn.b.al = DaUa;
558 RegsIn.b.ah = 0x8E;
559 Int386(0x1B, &RegsIn, &RegsOut);
560
561 /* Int 1Bh AH=84h
562 * DISK BIOS - Sense
563 *
564 * Call with:
565 * AL - drive number
566 *
567 * Return:
568 * BX - bytes per sector
569 * CX - cylinders number
570 * DH - heads number
571 * DL - sectors number
572 * CF - set on error, clear if successful
573 * AH - status
574 */
575 RegsIn.b.al = DaUa;
576 RegsIn.b.ah = 0x84;
577 Int386(0x1B, &RegsIn, &RegsOut);
578 if (!INT386_SUCCESS(RegsOut) || RegsOut.w.cx == 0)
579 {
580 DiskDrive->Initialized = FALSE;
581 return FALSE;
582 }
583
584 DiskDrive->Geometry.Cylinders = RegsOut.w.cx;
585 DiskDrive->Geometry.Heads = RegsOut.b.dh;
586 DiskDrive->Geometry.SectorsPerTrack = RegsOut.b.dl;
587 DiskDrive->Geometry.BytesPerSector = RegsOut.w.bx;
588
589 DiskDrive->Geometry.Sectors = (ULONGLONG)DiskDrive->Geometry.Cylinders *
590 DiskDrive->Geometry.Heads *
591 DiskDrive->Geometry.SectorsPerTrack;
592
593 DiskDrive->DaUa = DaUa;
594 DiskDrive->Type = DRIVE_IDE;
595 DiskDrive->LBASupported = FALSE;
596 DiskDrive->IsRemovable = FALSE;
597 DiskDrive->Initialized = TRUE;
598
599 TRACE("InitHardDrive(0x%x) returned:\n"
600 "Cylinders : 0x%x\n"
601 "Heads : 0x%x\n"
602 "Sects/Track: 0x%x\n"
603 "Bytes/Sect : 0x%x\n",
604 DaUa,
605 DiskDrive->Geometry.Cylinders,
606 DiskDrive->Geometry.Heads,
607 DiskDrive->Geometry.SectorsPerTrack,
608 DiskDrive->Geometry.BytesPerSector);
609
610 return TRUE;
611}
612
613static BOOLEAN
615 IN UCHAR DaUa,
616 IN OUT PPC98_DISK_DRIVE DiskDrive)
617{
618 REGS RegsIn, RegsOut;
619 USHORT BytesPerSector;
620 UCHAR DeviceAddress = DaUa & 0xF0;
621
622 /* There's no way to obtain floppy disk geometry in BIOS */
623
624 /* Int 1Bh AH=4Ah
625 * DISK BIOS - Read ID
626 *
627 * Call with:
628 * AL - drive number
629 *
630 * Return:
631 * CH - sector size
632 * CL - cylinder
633 * DH - head
634 * DL - sector
635 * CF - set on error, clear if successful
636 * AH - status
637 */
638 RegsIn.b.ah = 0x4A;
639 RegsIn.b.al = DaUa;
640 Int386(0x1B, &RegsIn, &RegsOut);
641 if (!INT386_SUCCESS(RegsOut))
642 {
643 DiskDrive->Initialized = FALSE;
644 return FALSE;
645 }
646
647 BytesPerSector = 128 << RegsOut.b.ch;
648 switch (BytesPerSector)
649 {
650 case 256:
651 if (DeviceAddress == 0x50)
652 {
653 /* 320 kB 2DD */
654 DiskDrive->Geometry.Cylinders = 80;
655 DiskDrive->Geometry.Heads = 2;
656 DiskDrive->Geometry.SectorsPerTrack = 16;
657 }
658 else
659 {
660 /* 1 MB 2HD */
661 DiskDrive->Geometry.Cylinders = 77;
662 DiskDrive->Geometry.Heads = 2;
663 DiskDrive->Geometry.SectorsPerTrack = 26;
664 }
665 break;
666
667 case 512:
668 if (DeviceAddress == 0x30 || DeviceAddress == 0xB0)
669 {
670 /* 1.44 MB 2HD */
671 DiskDrive->Geometry.Cylinders = 80;
672 DiskDrive->Geometry.Heads = 2;
673 DiskDrive->Geometry.SectorsPerTrack = 18;
674 }
675 else if (DeviceAddress == 0x70 || DeviceAddress == 0xF0)
676 {
677 /* 720/640 kB 2DD */
678 DiskDrive->Geometry.Cylinders = 80;
679 DiskDrive->Geometry.Heads = 2;
680 DiskDrive->Geometry.SectorsPerTrack = 8;
681 }
682 else
683 {
684 /* 1.2 MB 2HC */
685 DiskDrive->Geometry.Cylinders = 80;
686 DiskDrive->Geometry.Heads = 2;
687 DiskDrive->Geometry.SectorsPerTrack = 15;
688 }
689 break;
690
691 case 1024:
692 /* 1.25 MB 2HD */
693 DiskDrive->Geometry.Cylinders = 77;
694 DiskDrive->Geometry.Heads = 2;
695 DiskDrive->Geometry.SectorsPerTrack = 8;
696 break;
697
698 default:
699 DiskDrive->Initialized = FALSE;
700 return FALSE;
701 }
702
703 DiskDrive->Geometry.BytesPerSector = BytesPerSector;
704 DiskDrive->Geometry.Sectors = (ULONGLONG)DiskDrive->Geometry.Cylinders *
705 DiskDrive->Geometry.Heads *
706 DiskDrive->Geometry.SectorsPerTrack;
707
708 DiskDrive->DaUa = DaUa;
709 DiskDrive->Type = DRIVE_FDD;
710 DiskDrive->LBASupported = FALSE;
711 DiskDrive->IsRemovable = TRUE;
712 DiskDrive->Initialized = TRUE;
713
714 TRACE("InitFloppyDrive(0x%x) returned:\n"
715 "Cylinders : 0x%x\n"
716 "Heads : 0x%x\n"
717 "Sects/Track: 0x%x\n"
718 "Bytes/Sect : 0x%x\n",
719 DaUa,
720 DiskDrive->Geometry.Cylinders,
721 DiskDrive->Geometry.Heads,
722 DiskDrive->Geometry.SectorsPerTrack,
723 DiskDrive->Geometry.BytesPerSector);
724
725 return TRUE;
726}
727
728/* We emulate PC BIOS drive numbers here */
731{
732 PPC98_DISK_DRIVE DiskDrive;
733 UCHAR FakeFloppyDriveNumber = 0x30;
734 UCHAR FakeHardDriveDriveNumber = 0x80;
735 UCHAR FakeCdRomDriveNumber = 0xE0;
736 USHORT DiskEquipment = *(PUSHORT)MEM_DISK_EQUIP & ~(*(PUCHAR)MEM_RDISK_EQUIP);
737 UCHAR IdeDetectedCount;
738 UCHAR i;
739
740 TRACE("Pc98InitializeBootDevices()\n");
741
743
744 /*
745 * Map DA/UA to drive number, i.e.
746 * 0x90 -> 0x30
747 * 0x80 -> 0x80
748 * 0xA0 -> 0x81, etc.
749 */
750
751 /* Map floppies */
752
753 for (i = 0; i < 4; i++)
754 {
755 DiskDrive = &Pc98DiskDrive[FakeFloppyDriveNumber];
756 if (FIRSTBYTE(DiskEquipment) & (1 << i))
757 {
758 if (InitFloppyDrive(0x30 + i, DiskDrive) || InitFloppyDrive(0xB0 + i, DiskDrive) ||
759 InitFloppyDrive(0x90 + i, DiskDrive) || InitFloppyDrive(0x10 + i, DiskDrive))
760 ++FakeFloppyDriveNumber;
761 }
762 }
763
764 for (i = 0; i < 4; i++)
765 {
766 DiskDrive = &Pc98DiskDrive[FakeFloppyDriveNumber];
767 if (FIRSTBYTE(DiskEquipment) & (16 << i))
768 {
769 if (InitFloppyDrive(0x50 + i, DiskDrive))
770 ++FakeFloppyDriveNumber;
771 }
772 }
773
774 for (i = 0; i < 4; i++)
775 {
776 DiskDrive = &Pc98DiskDrive[FakeFloppyDriveNumber];
777 if (SECONDBYTE(DiskEquipment) & (16 << i))
778 {
779 if (InitFloppyDrive(0x70 + i, DiskDrive) || InitFloppyDrive(0xF0 + i, DiskDrive))
780 ++FakeFloppyDriveNumber;
781 }
782 }
783
784 /* Map IDE/SASI drives */
785
786 for (i = 0; i < 4; i++)
787 {
788 DiskDrive = &Pc98DiskDrive[FakeHardDriveDriveNumber];
789 if (InitHardDrive(0x80 + i, DiskDrive) || InitHardDrive(0x00 + i, DiskDrive))
790 ++FakeHardDriveDriveNumber;
791 }
792
793 AtaInit(&IdeDetectedCount);
794 for (i = 0; i <= IdeDetectedCount; i++)
795 {
796 DiskDrive = &Pc98DiskDrive[FakeCdRomDriveNumber];
797 if (InitIdeDrive(i, DiskDrive))
798 ++FakeCdRomDriveNumber;
799 }
800
801 /* Map SCSI drives */
802
803 for (i = 0; i < 7; i++)
804 {
805 DiskDrive = &Pc98DiskDrive[FakeHardDriveDriveNumber];
806 if (InitScsiDrive(0xA0 + i, DiskDrive) || InitScsiDrive(0x20 + i, DiskDrive))
807 {
808 if (DiskDrive->Type & DRIVE_CDROM || DiskDrive->Type & DRIVE_MO)
809 {
810 /* Move to CD-ROM area */
811 Pc98DiskDrive[FakeCdRomDriveNumber] = *DiskDrive;
812 RtlZeroMemory(DiskDrive, sizeof(PC98_DISK_DRIVE));
813 ++FakeCdRomDriveNumber;
814 }
815 else
816 {
817 ++FakeHardDriveDriveNumber;
818 }
819 }
820 }
821
822#if 1
823 // Ugly HACK: Force ISO boot
824 // FIXME: Fill ARC disk blocks completely
825 // to allow usage of CD-ROM root path (See floppy_pc98.ini).
826 FrldrBootDrive = 0xE0;
827 FrldrBootPartition = 0xFF;
828#else
829 /* Reassign boot drive */
830 for (i = 0; i < MAX_DRIVES - 1; i++)
831 {
832 DiskDrive = &Pc98DiskDrive[i];
833 if (DiskDrive->Initialized && DiskDrive->DaUa == FrldrBootDrive)
834 {
835 TRACE("Boot drive: old 0x%x, new 0x%x\n", FrldrBootDrive, i);
837 break;
838 }
839 }
840#endif
841
842 /* Call PC version */
844}
845
848 IN UCHAR DriveNumber,
849 IN ULONGLONG SectorNumber,
852{
853 PPC98_DISK_DRIVE DiskDrive;
854
855 TRACE("Pc98DiskReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d Buffer: 0x%x\n",
856 DriveNumber, SectorNumber, SectorCount, Buffer);
857
858 /* 16-bit BIOS addressing limitation */
859 ASSERT(((ULONG_PTR)Buffer) <= 0xFFFFF);
860
861 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber);
862 if (!DiskDrive)
863 return FALSE;
864
865 if (DiskDrive->LBASupported)
866 {
867 /* LBA is easy, nothing to calculate. Just do the read. */
868 TRACE("--> Using LBA\n");
869 return Pc98DiskReadLogicalSectorsLBA(DiskDrive, SectorNumber, SectorCount, Buffer);
870 }
871 else
872 {
873 /* LBA is not supported, default to CHS */
874 TRACE("--> Using CHS\n");
875 return Pc98DiskReadLogicalSectorsCHS(DiskDrive, SectorNumber, SectorCount, Buffer);
876 }
877}
878
881{
882 PPC98_DISK_DRIVE DiskDrive;
883
884 TRACE("Pc98DiskGetDriveGeometry(0x%x)\n", DriveNumber);
885
886 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber);
887 if (!DiskDrive)
888 return FALSE;
889
890 *Geometry = DiskDrive->Geometry;
891
892 return TRUE;
893}
894
895ULONG
897{
898 PPC98_DISK_DRIVE DiskDrive;
899
900 DiskDrive = Pc98DiskDriveNumberToDrive(DriveNumber);
901 if (!DiskDrive)
902 return 1; // Unknown count.
903
904 /*
905 * If LBA is supported then the block size will be 64 sectors (32k).
906 * If not then the block size is the size of one track.
907 */
908 if (DiskDrive->LBASupported)
909 return 64;
910 else
911 return DiskDrive->Geometry.SectorsPerTrack;
912}
unsigned char BOOLEAN
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
VOID UiMessageBox(_In_ PCSTR Format,...)
Definition: ui.c:359
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:473
PDEVICE_UNIT AtaGetDevice(IN UCHAR UnitNumber)
Definition: hwide.c:178
BOOLEAN AtaAtapiReadLogicalSectorsLBA(IN OUT PDEVICE_UNIT DeviceUnit, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
Definition: hwide.c:187
BOOLEAN AtaInit(OUT PUCHAR DetectedCount)
Definition: hwide.c:139
VOID AtaFree()
#define ATA_DEVICE_ATAPI
Definition: hwide.h:303
#define DRIVE_SCSI
Definition: machpc98.h:118
#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_MO
Definition: machpc98.h:121
#define DRIVE_IDE
Definition: machpc98.h:117
#define MEM_DISK_EQUIPS
Definition: machpc98.h:30
#define DRIVE_CDROM
Definition: machpc98.h:119
#define DRIVE_FDD
Definition: machpc98.h:120
DeviceType
Definition: mmdrv.h:42
#define ASSERT(a)
Definition: mode.c:44
#define min(a, b)
Definition: monoChain.cc:55
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4436
NTSTRSAFEVAPI RtlStringCbPrintfA(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,...)
Definition: ntstrsafe.h:1148
ULONG SectorCount
Definition: part_xbox.c:31
ULONG Pc98DiskGetCacheableBlockCount(UCHAR DriveNumber)
Definition: pc98disk.c:896
static LONG lReportError
Definition: pc98disk.c:26
static BOOLEAN InitHardDrive(IN UCHAR DaUa, IN OUT PPC98_DISK_DRIVE DiskDrive)
Definition: pc98disk.c:545
static PCSTR DiskGetErrorCodeString(ULONG ErrorCode)
Definition: pc98disk.c:40
PPC98_DISK_DRIVE Pc98DiskDriveNumberToDrive(IN UCHAR DriveNumber)
Definition: pc98disk.c:141
PC98_DISK_DRIVE Pc98DiskDrive[MAX_DRIVES]
Definition: pc98disk.c:22
static BOOLEAN Pc98DiskReadLogicalSectorsLBA(IN PPC98_DISK_DRIVE DiskDrive, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
Definition: pc98disk.c:179
BOOLEAN DiskResetController(IN PPC98_DISK_DRIVE DiskDrive)
Definition: pc98disk.c:91
LONG DiskReportError(BOOLEAN bShowError)
Definition: pc98disk.c:29
VOID Pc98DiskPrepareForReactOS(VOID)
Definition: pc98disk.c:135
BOOLEAN Pc98InitializeBootDevices(VOID)
Definition: pc98disk.c:730
static BOOLEAN InitFloppyDrive(IN UCHAR DaUa, IN OUT PPC98_DISK_DRIVE DiskDrive)
Definition: pc98disk.c:614
BOOLEAN Pc98DiskReadLogicalSectors(IN UCHAR DriveNumber, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
Definition: pc98disk.c:847
static BOOLEAN Pc98DiskReadLogicalSectorsCHS(IN PPC98_DISK_DRIVE DiskDrive, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
Definition: pc98disk.c:251
#define MAX_DRIVES
Definition: pc98disk.c:19
static BOOLEAN InitIdeDrive(IN UCHAR UnitNumber, IN OUT PPC98_DISK_DRIVE DiskDrive)
Definition: pc98disk.c:504
static BOOLEAN InitScsiDrive(IN UCHAR DaUa, IN OUT PPC98_DISK_DRIVE DiskDrive)
Definition: pc98disk.c:399
static UCHAR BytesPerSectorToSectorLengthCode(IN ULONG BytesPerSector)
Definition: pc98disk.c:159
BOOLEAN Pc98DiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
Definition: pc98disk.c:880
static VOID DiskError(PCSTR ErrorString, ULONG ErrorCode)
Definition: pc98disk.c:74
#define INT386_SUCCESS(regs)
Definition: pcbios.h:179
int __cdecl Int386(int ivec, REGS *in, REGS *out)
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define TRACE(s)
Definition: solgame.cpp:4
unsigned char ch
Definition: pcbios.h:138
unsigned char dl
Definition: pcbios.h:140
unsigned char cl
Definition: pcbios.h:137
unsigned char al
Definition: pcbios.h:131
unsigned char ah
Definition: pcbios.h:132
unsigned char dh
Definition: pcbios.h:141
unsigned short bp
Definition: pcbios.h:118
unsigned short es
Definition: pcbios.h:121
unsigned short cx
Definition: pcbios.h:113
unsigned short dx
Definition: pcbios.h:114
unsigned short bx
Definition: pcbios.h:112
USHORT Flags
Definition: hwide.h:299
ULONG Cylinders
Definition: hwide.h:294
ULONG SectorSize
Definition: hwide.h:297
ULONG Sectors
Definition: hwide.h:296
ULONGLONG TotalSectors
Definition: hwide.h:298
ULONG Heads
Definition: hwide.h:295
Definition: disk.h:26
ULONG BytesPerSector
Number of bytes per sector.
Definition: disk.h:30
ULONG Cylinders
Number of cylinders on the disk.
Definition: disk.h:27
ULONG SectorsPerTrack
Number of sectors per track.
Definition: disk.h:29
ULONG Heads
Number of heads on the disk.
Definition: disk.h:28
BOOLEAN LBASupported
Definition: machpc98.h:125
GEOMETRY Geometry
Definition: machpc98.h:106
BOOLEAN Initialized
Definition: machpc98.h:137
uint32_t * PULONG
Definition: typedefs.h:59
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
#define IN
Definition: typedefs.h:39
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define OUT
Definition: typedefs.h:40
UCHAR FrldrBootDrive
Definition: uefidisk.c:47
ULONG FrldrBootPartition
Definition: uefidisk.c:48
Definition: pcbios.h:159
BYTEREGS b
Definition: pcbios.h:163
WORDREGS w
Definition: pcbios.h:162
#define SECONDBYTE(VALUE)
Definition: rtlfuncs.h:804
#define FIRSTBYTE(VALUE)
Definition: rtlfuncs.h:803
unsigned char UCHAR
Definition: xmlstorage.h:181
char CHAR
Definition: xmlstorage.h:175