|
@@ -75,9 +75,9 @@ struct int13_drive {
|
75
|
75
|
/** Underlying block device interface */
|
76
|
76
|
struct interface block;
|
77
|
77
|
|
78
|
|
- /** BIOS in-use drive number (0x80-0xff) */
|
|
78
|
+ /** BIOS in-use drive number (0x00-0xff) */
|
79
|
79
|
unsigned int drive;
|
80
|
|
- /** BIOS natural drive number (0x80-0xff)
|
|
80
|
+ /** BIOS natural drive number (0x00-0xff)
|
81
|
81
|
*
|
82
|
82
|
* This is the drive number that would have been assigned by
|
83
|
83
|
* 'naturally' appending the drive to the end of the BIOS
|
|
@@ -142,17 +142,44 @@ static struct segoff __text16 ( int13_vector );
|
142
|
142
|
/** Assembly wrapper */
|
143
|
143
|
extern void int13_wrapper ( void );
|
144
|
144
|
|
|
145
|
+/** Dummy floppy disk parameter table */
|
|
146
|
+static struct int13_fdd_parameters __data16 ( int13_fdd_params ) = {
|
|
147
|
+ /* 512 bytes per sector */
|
|
148
|
+ .bytes_per_sector = 0x02,
|
|
149
|
+ /* Highest sectors per track that we ever return */
|
|
150
|
+ .sectors_per_track = 48,
|
|
151
|
+};
|
|
152
|
+#define int13_fdd_params __use_data16 ( int13_fdd_params )
|
|
153
|
+
|
145
|
154
|
/** List of registered emulated drives */
|
146
|
155
|
static LIST_HEAD ( int13s );
|
147
|
156
|
|
148
|
157
|
/**
|
149
|
|
- * Number of BIOS drives
|
|
158
|
+ * Equipment word
|
|
159
|
+ *
|
|
160
|
+ * This is a cached copy of the BIOS Data Area equipment word at
|
|
161
|
+ * 40:10.
|
|
162
|
+ */
|
|
163
|
+static uint16_t equipment_word;
|
|
164
|
+
|
|
165
|
+/**
|
|
166
|
+ * Number of BIOS floppy disk drives
|
150
|
167
|
*
|
151
|
|
- * Note that this is the number of drives in the system as a whole
|
152
|
|
- * (i.e. a mirror of the counter at 40:75), rather than a count of the
|
153
|
|
- * number of emulated drives.
|
|
168
|
+ * This is derived from the equipment word. It is held in .text16 to
|
|
169
|
+ * allow for easy access by the INT 13,08 wrapper.
|
154
|
170
|
*/
|
155
|
|
-static uint8_t num_drives;
|
|
171
|
+static uint8_t __text16 ( num_fdds );
|
|
172
|
+#define num_fdds __use_text16 ( num_fdds )
|
|
173
|
+
|
|
174
|
+/**
|
|
175
|
+ * Number of BIOS hard disk drives
|
|
176
|
+ *
|
|
177
|
+ * This is a cached copy of the BIOS Data Area number of hard disk
|
|
178
|
+ * drives at 40:75. It is held in .text16 to allow for easy access by
|
|
179
|
+ * the INT 13,08 wrapper.
|
|
180
|
+ */
|
|
181
|
+static uint8_t __text16 ( num_drives );
|
|
182
|
+#define num_drives __use_text16 ( num_drives )
|
156
|
183
|
|
157
|
184
|
/**
|
158
|
185
|
* Calculate INT 13 drive sector size
|
|
@@ -185,6 +212,16 @@ static inline uint32_t int13_capacity32 ( struct int13_drive *int13 ) {
|
185
|
212
|
return ( ( capacity <= 0xffffffffUL ) ? capacity : 0xffffffff );
|
186
|
213
|
}
|
187
|
214
|
|
|
215
|
+/**
|
|
216
|
+ * Test if INT 13 drive is a floppy disk drive
|
|
217
|
+ *
|
|
218
|
+ * @v int13 Emulated drive
|
|
219
|
+ * @ret is_fdd Emulated drive is a floppy disk
|
|
220
|
+ */
|
|
221
|
+static inline int int13_is_fdd ( struct int13_drive *int13 ) {
|
|
222
|
+ return ( ! ( int13->drive & 0x80 ) );
|
|
223
|
+}
|
|
224
|
+
|
188
|
225
|
/** An INT 13 command */
|
189
|
226
|
struct int13_command {
|
190
|
227
|
/** Status */
|
|
@@ -499,33 +536,33 @@ static int int13_parse_iso9660 ( struct int13_drive *int13, void *scratch ) {
|
499
|
536
|
}
|
500
|
537
|
|
501
|
538
|
/**
|
502
|
|
- * Guess INT 13 drive geometry
|
|
539
|
+ * Guess INT 13 hard disk drive geometry
|
503
|
540
|
*
|
504
|
541
|
* @v int13 Emulated drive
|
505
|
542
|
* @v scratch Scratch area for single-sector reads
|
|
543
|
+ * @ret heads Guessed number of heads
|
|
544
|
+ * @ret sectors Guessed number of sectors per track
|
506
|
545
|
* @ret rc Return status code
|
507
|
546
|
*
|
508
|
547
|
* Guesses the drive geometry by inspecting the partition table.
|
509
|
548
|
*/
|
510
|
|
-static int int13_guess_geometry ( struct int13_drive *int13, void *scratch ) {
|
|
549
|
+static int int13_guess_geometry_hdd ( struct int13_drive *int13, void *scratch,
|
|
550
|
+ unsigned int *heads,
|
|
551
|
+ unsigned int *sectors ) {
|
511
|
552
|
struct master_boot_record *mbr = scratch;
|
512
|
553
|
struct partition_table_entry *partition;
|
513
|
|
- unsigned int guessed_heads = 255;
|
514
|
|
- unsigned int guessed_sectors_per_track = 63;
|
515
|
|
- unsigned int blocks;
|
516
|
|
- unsigned int blocks_per_cyl;
|
517
|
554
|
unsigned int i;
|
518
|
555
|
int rc;
|
519
|
556
|
|
520
|
|
- /* Don't even try when the blksize is invalid for C/H/S access */
|
521
|
|
- if ( int13_blksize ( int13 ) != INT13_BLKSIZE )
|
522
|
|
- return 0;
|
|
557
|
+ /* Default guess is xx/255/63 */
|
|
558
|
+ *heads = 255;
|
|
559
|
+ *sectors = 63;
|
523
|
560
|
|
524
|
561
|
/* Read partition table */
|
525
|
562
|
if ( ( rc = int13_rw ( int13, 0, 1, virt_to_user ( mbr ),
|
526
|
563
|
block_read ) ) != 0 ) {
|
527
|
|
- DBGC ( int13, "INT13 drive %02x could not read partition "
|
528
|
|
- "table to guess geometry: %s\n",
|
|
564
|
+ DBGC ( int13, "INT13 drive %02x could not read "
|
|
565
|
+ "partition table to guess geometry: %s\n",
|
529
|
566
|
int13->drive, strerror ( rc ) );
|
530
|
567
|
return rc;
|
531
|
568
|
}
|
|
@@ -534,25 +571,126 @@ static int int13_guess_geometry ( struct int13_drive *int13, void *scratch ) {
|
534
|
571
|
DBGC ( int13, "INT13 drive %02x has signature %08x\n",
|
535
|
572
|
int13->drive, mbr->signature );
|
536
|
573
|
|
537
|
|
- /* Scan through partition table and modify guesses for heads
|
538
|
|
- * and sectors_per_track if we find any used partitions.
|
|
574
|
+ /* Scan through partition table and modify guesses for
|
|
575
|
+ * heads and sectors_per_track if we find any used
|
|
576
|
+ * partitions.
|
539
|
577
|
*/
|
540
|
578
|
for ( i = 0 ; i < 4 ; i++ ) {
|
541
|
579
|
partition = &mbr->partitions[i];
|
542
|
580
|
if ( ! partition->type )
|
543
|
581
|
continue;
|
544
|
|
- guessed_heads = ( PART_HEAD ( partition->chs_end ) + 1 );
|
545
|
|
- guessed_sectors_per_track = PART_SECTOR ( partition->chs_end );
|
|
582
|
+ *heads = ( PART_HEAD ( partition->chs_end ) + 1 );
|
|
583
|
+ *sectors = PART_SECTOR ( partition->chs_end );
|
546
|
584
|
DBGC ( int13, "INT13 drive %02x guessing C/H/S xx/%d/%d based "
|
547
|
|
- "on partition %d\n", int13->drive, guessed_heads,
|
548
|
|
- guessed_sectors_per_track, ( i + 1 ) );
|
|
585
|
+ "on partition %d\n",
|
|
586
|
+ int13->drive, *heads, *sectors, ( i + 1 ) );
|
|
587
|
+ }
|
|
588
|
+
|
|
589
|
+ return 0;
|
|
590
|
+}
|
|
591
|
+
|
|
592
|
+/** Recognised floppy disk geometries */
|
|
593
|
+static const struct int13_fdd_geometry int13_fdd_geometries[] = {
|
|
594
|
+ INT13_FDD_GEOMETRY ( 40, 1, 8 ),
|
|
595
|
+ INT13_FDD_GEOMETRY ( 40, 1, 9 ),
|
|
596
|
+ INT13_FDD_GEOMETRY ( 40, 2, 8 ),
|
|
597
|
+ INT13_FDD_GEOMETRY ( 40, 1, 9 ),
|
|
598
|
+ INT13_FDD_GEOMETRY ( 80, 2, 8 ),
|
|
599
|
+ INT13_FDD_GEOMETRY ( 80, 2, 9 ),
|
|
600
|
+ INT13_FDD_GEOMETRY ( 80, 2, 15 ),
|
|
601
|
+ INT13_FDD_GEOMETRY ( 80, 2, 18 ),
|
|
602
|
+ INT13_FDD_GEOMETRY ( 80, 2, 20 ),
|
|
603
|
+ INT13_FDD_GEOMETRY ( 80, 2, 21 ),
|
|
604
|
+ INT13_FDD_GEOMETRY ( 82, 2, 21 ),
|
|
605
|
+ INT13_FDD_GEOMETRY ( 83, 2, 21 ),
|
|
606
|
+ INT13_FDD_GEOMETRY ( 80, 2, 22 ),
|
|
607
|
+ INT13_FDD_GEOMETRY ( 80, 2, 23 ),
|
|
608
|
+ INT13_FDD_GEOMETRY ( 80, 2, 24 ),
|
|
609
|
+ INT13_FDD_GEOMETRY ( 80, 2, 36 ),
|
|
610
|
+ INT13_FDD_GEOMETRY ( 80, 2, 39 ),
|
|
611
|
+ INT13_FDD_GEOMETRY ( 80, 2, 40 ),
|
|
612
|
+ INT13_FDD_GEOMETRY ( 80, 2, 44 ),
|
|
613
|
+ INT13_FDD_GEOMETRY ( 80, 2, 48 ),
|
|
614
|
+};
|
|
615
|
+
|
|
616
|
+/**
|
|
617
|
+ * Guess INT 13 floppy disk drive geometry
|
|
618
|
+ *
|
|
619
|
+ * @v int13 Emulated drive
|
|
620
|
+ * @ret heads Guessed number of heads
|
|
621
|
+ * @ret sectors Guessed number of sectors per track
|
|
622
|
+ * @ret rc Return status code
|
|
623
|
+ *
|
|
624
|
+ * Guesses the drive geometry by inspecting the disk size.
|
|
625
|
+ */
|
|
626
|
+static int int13_guess_geometry_fdd ( struct int13_drive *int13,
|
|
627
|
+ unsigned int *heads,
|
|
628
|
+ unsigned int *sectors ) {
|
|
629
|
+ unsigned int blocks = int13_blksize ( int13 );
|
|
630
|
+ const struct int13_fdd_geometry *geometry;
|
|
631
|
+ unsigned int cylinders;
|
|
632
|
+ unsigned int i;
|
|
633
|
+
|
|
634
|
+ /* Look for a match against a known geometry */
|
|
635
|
+ for ( i = 0 ; i < ( sizeof ( int13_fdd_geometries ) /
|
|
636
|
+ sizeof ( int13_fdd_geometries[0] ) ) ; i++ ) {
|
|
637
|
+ geometry = &int13_fdd_geometries[i];
|
|
638
|
+ cylinders = INT13_FDD_CYLINDERS ( geometry );
|
|
639
|
+ *heads = INT13_FDD_HEADS ( geometry );
|
|
640
|
+ *sectors = INT13_FDD_SECTORS ( geometry );
|
|
641
|
+ if ( ( cylinders * (*heads) * (*sectors) ) == blocks ) {
|
|
642
|
+ DBGC ( int13, "INT13 drive %02x guessing C/H/S "
|
|
643
|
+ "%d/%d/%d based on size %dK\n", int13->drive,
|
|
644
|
+ cylinders, *heads, *sectors, ( blocks / 2 ) );
|
|
645
|
+ return 0;
|
|
646
|
+ }
|
|
647
|
+ }
|
|
648
|
+
|
|
649
|
+ /* Otherwise, assume a partial disk image in the most common
|
|
650
|
+ * format (1440K, 80/2/18).
|
|
651
|
+ */
|
|
652
|
+ *heads = 2;
|
|
653
|
+ *sectors = 18;
|
|
654
|
+ DBGC ( int13, "INT13 drive %02x guessing C/H/S xx/%d/%d based on size "
|
|
655
|
+ "%dK\n", int13->drive, *heads, *sectors, ( blocks / 2 ) );
|
|
656
|
+ return 0;
|
|
657
|
+}
|
|
658
|
+
|
|
659
|
+/**
|
|
660
|
+ * Guess INT 13 drive geometry
|
|
661
|
+ *
|
|
662
|
+ * @v int13 Emulated drive
|
|
663
|
+ * @v scratch Scratch area for single-sector reads
|
|
664
|
+ * @ret rc Return status code
|
|
665
|
+ */
|
|
666
|
+static int int13_guess_geometry ( struct int13_drive *int13, void *scratch ) {
|
|
667
|
+ unsigned int guessed_heads;
|
|
668
|
+ unsigned int guessed_sectors;
|
|
669
|
+ unsigned int blocks;
|
|
670
|
+ unsigned int blocks_per_cyl;
|
|
671
|
+ int rc;
|
|
672
|
+
|
|
673
|
+ /* Don't even try when the blksize is invalid for C/H/S access */
|
|
674
|
+ if ( int13_blksize ( int13 ) != INT13_BLKSIZE )
|
|
675
|
+ return 0;
|
|
676
|
+
|
|
677
|
+ /* Guess geometry according to drive type */
|
|
678
|
+ if ( int13_is_fdd ( int13 ) ) {
|
|
679
|
+ if ( ( rc = int13_guess_geometry_fdd ( int13, &guessed_heads,
|
|
680
|
+ &guessed_sectors )) != 0)
|
|
681
|
+ return rc;
|
|
682
|
+ } else {
|
|
683
|
+ if ( ( rc = int13_guess_geometry_hdd ( int13, scratch,
|
|
684
|
+ &guessed_heads,
|
|
685
|
+ &guessed_sectors )) != 0)
|
|
686
|
+ return rc;
|
549
|
687
|
}
|
550
|
688
|
|
551
|
689
|
/* Apply guesses if no geometry already specified */
|
552
|
690
|
if ( ! int13->heads )
|
553
|
691
|
int13->heads = guessed_heads;
|
554
|
692
|
if ( ! int13->sectors_per_track )
|
555
|
|
- int13->sectors_per_track = guessed_sectors_per_track;
|
|
693
|
+ int13->sectors_per_track = guessed_sectors;
|
556
|
694
|
if ( ! int13->cylinders ) {
|
557
|
695
|
/* Avoid attempting a 64-bit divide on a 32-bit system */
|
558
|
696
|
blocks = int13_capacity32 ( int13 );
|
|
@@ -569,19 +707,40 @@ static int int13_guess_geometry ( struct int13_drive *int13, void *scratch ) {
|
569
|
707
|
/**
|
570
|
708
|
* Update BIOS drive count
|
571
|
709
|
*/
|
572
|
|
-static void int13_set_num_drives ( void ) {
|
|
710
|
+static void int13_sync_num_drives ( void ) {
|
573
|
711
|
struct int13_drive *int13;
|
|
712
|
+ uint8_t *counter;
|
|
713
|
+ uint8_t max_drive;
|
|
714
|
+ uint8_t required;
|
574
|
715
|
|
575
|
|
- /* Get current drive count */
|
|
716
|
+ /* Get current drive counts */
|
|
717
|
+ get_real ( equipment_word, BDA_SEG, BDA_EQUIPMENT_WORD );
|
576
|
718
|
get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
|
|
719
|
+ num_fdds = ( ( equipment_word & 0x0001 ) ?
|
|
720
|
+ ( ( ( equipment_word >> 6 ) & 0x3 ) + 1 ) : 0 );
|
577
|
721
|
|
578
|
722
|
/* Ensure count is large enough to cover all of our emulated drives */
|
579
|
723
|
list_for_each_entry ( int13, &int13s, list ) {
|
580
|
|
- if ( num_drives <= ( int13->drive & 0x7f ) )
|
581
|
|
- num_drives = ( ( int13->drive & 0x7f ) + 1 );
|
|
724
|
+ counter = ( int13_is_fdd ( int13 ) ? &num_fdds : &num_drives );
|
|
725
|
+ max_drive = int13->drive;
|
|
726
|
+ if ( max_drive < int13->natural_drive )
|
|
727
|
+ max_drive = int13->natural_drive;
|
|
728
|
+ required = ( ( max_drive & 0x7f ) + 1 );
|
|
729
|
+ if ( *counter < required ) {
|
|
730
|
+ *counter = required;
|
|
731
|
+ DBGC ( int13, "INT13 drive %02x added to drive count: "
|
|
732
|
+ "%d HDDs, %d FDDs\n",
|
|
733
|
+ int13->drive, num_drives, num_fdds );
|
|
734
|
+ }
|
582
|
735
|
}
|
583
|
736
|
|
584
|
737
|
/* Update current drive count */
|
|
738
|
+ equipment_word &= ~( ( 0x3 << 6 ) | 0x0001 );
|
|
739
|
+ if ( num_fdds ) {
|
|
740
|
+ equipment_word |= ( 0x0001 |
|
|
741
|
+ ( ( ( num_fdds - 1 ) & 0x3 ) << 6 ) );
|
|
742
|
+ }
|
|
743
|
+ put_real ( equipment_word, BDA_SEG, BDA_EQUIPMENT_WORD );
|
585
|
744
|
put_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
|
586
|
745
|
}
|
587
|
746
|
|
|
@@ -589,13 +748,14 @@ static void int13_set_num_drives ( void ) {
|
589
|
748
|
* Check number of drives
|
590
|
749
|
*/
|
591
|
750
|
static void int13_check_num_drives ( void ) {
|
|
751
|
+ uint16_t check_equipment_word;
|
592
|
752
|
uint8_t check_num_drives;
|
593
|
753
|
|
|
754
|
+ get_real ( check_equipment_word, BDA_SEG, BDA_EQUIPMENT_WORD );
|
594
|
755
|
get_real ( check_num_drives, BDA_SEG, BDA_NUM_DRIVES );
|
595
|
|
- if ( check_num_drives != num_drives ) {
|
596
|
|
- int13_set_num_drives();
|
597
|
|
- DBG ( "INT13 fixing up number of drives from %d to %d\n",
|
598
|
|
- check_num_drives, num_drives );
|
|
756
|
+ if ( ( check_equipment_word != equipment_word ) ||
|
|
757
|
+ ( check_num_drives != num_drives ) ) {
|
|
758
|
+ int13_sync_num_drives();
|
599
|
759
|
}
|
600
|
760
|
}
|
601
|
761
|
|
|
@@ -669,14 +829,19 @@ static int int13_rw_sectors ( struct int13_drive *int13,
|
669
|
829
|
int13->drive, int13_blksize ( int13 ) );
|
670
|
830
|
return -INT13_STATUS_INVALID;
|
671
|
831
|
}
|
672
|
|
-
|
|
832
|
+
|
673
|
833
|
/* Calculate parameters */
|
674
|
834
|
cylinder = ( ( ( ix86->regs.cl & 0xc0 ) << 2 ) | ix86->regs.ch );
|
675
|
|
- assert ( cylinder < int13->cylinders );
|
676
|
835
|
head = ix86->regs.dh;
|
677
|
|
- assert ( head < int13->heads );
|
678
|
836
|
sector = ( ix86->regs.cl & 0x3f );
|
679
|
|
- assert ( ( sector >= 1 ) && ( sector <= int13->sectors_per_track ) );
|
|
837
|
+ if ( ( cylinder >= int13->cylinders ) ||
|
|
838
|
+ ( head >= int13->heads ) ||
|
|
839
|
+ ( sector < 1 ) || ( sector > int13->sectors_per_track ) ) {
|
|
840
|
+ DBGC ( int13, "C/H/S %d/%d/%d out of range for geometry "
|
|
841
|
+ "%d/%d/%d\n", cylinder, head, sector, int13->cylinders,
|
|
842
|
+ int13->heads, int13->sectors_per_track );
|
|
843
|
+ return -INT13_STATUS_INVALID;
|
|
844
|
+ }
|
680
|
845
|
lba = ( ( ( ( cylinder * int13->heads ) + head )
|
681
|
846
|
* int13->sectors_per_track ) + sector - 1 );
|
682
|
847
|
count = ix86->regs.al;
|
|
@@ -761,10 +926,19 @@ static int int13_get_parameters ( struct int13_drive *int13,
|
761
|
926
|
return -INT13_STATUS_INVALID;
|
762
|
927
|
}
|
763
|
928
|
|
|
929
|
+ /* Common parameters */
|
764
|
930
|
ix86->regs.ch = ( max_cylinder & 0xff );
|
765
|
931
|
ix86->regs.cl = ( ( ( max_cylinder >> 8 ) << 6 ) | max_sector );
|
766
|
932
|
ix86->regs.dh = max_head;
|
767
|
|
- get_real ( ix86->regs.dl, BDA_SEG, BDA_NUM_DRIVES );
|
|
933
|
+ ix86->regs.dl = ( int13_is_fdd ( int13 ) ? num_fdds : num_drives );
|
|
934
|
+
|
|
935
|
+ /* Floppy-specific parameters */
|
|
936
|
+ if ( int13_is_fdd ( int13 ) ) {
|
|
937
|
+ ix86->regs.bl = INT13_FDD_TYPE_1M44;
|
|
938
|
+ ix86->segs.es = rm_ds;
|
|
939
|
+ ix86->regs.di = __from_data16 ( &int13_fdd_params );
|
|
940
|
+ }
|
|
941
|
+
|
768
|
942
|
return 0;
|
769
|
943
|
}
|
770
|
944
|
|
|
@@ -781,10 +955,15 @@ static int int13_get_disk_type ( struct int13_drive *int13,
|
781
|
955
|
uint32_t blocks;
|
782
|
956
|
|
783
|
957
|
DBGC2 ( int13, "Get disk type\n" );
|
784
|
|
- blocks = int13_capacity32 ( int13 );
|
785
|
|
- ix86->regs.cx = ( blocks >> 16 );
|
786
|
|
- ix86->regs.dx = ( blocks & 0xffff );
|
787
|
|
- return INT13_DISK_TYPE_HDD;
|
|
958
|
+
|
|
959
|
+ if ( int13_is_fdd ( int13 ) ) {
|
|
960
|
+ return INT13_DISK_TYPE_FDD;
|
|
961
|
+ } else {
|
|
962
|
+ blocks = int13_capacity32 ( int13 );
|
|
963
|
+ ix86->regs.cx = ( blocks >> 16 );
|
|
964
|
+ ix86->regs.dx = ( blocks & 0xffff );
|
|
965
|
+ return INT13_DISK_TYPE_HDD;
|
|
966
|
+ }
|
788
|
967
|
}
|
789
|
968
|
|
790
|
969
|
/**
|
|
@@ -833,6 +1012,13 @@ static int int13_extended_rw ( struct int13_drive *int13,
|
833
|
1012
|
userptr_t buffer;
|
834
|
1013
|
int rc;
|
835
|
1014
|
|
|
1015
|
+ /* Extended reads are not allowed on floppy drives.
|
|
1016
|
+ * ELTORITO.SYS seems to assume that we are really a CD-ROM if
|
|
1017
|
+ * we support extended reads for a floppy drive.
|
|
1018
|
+ */
|
|
1019
|
+ if ( int13_is_fdd ( int13 ) )
|
|
1020
|
+ return -INT13_STATUS_INVALID;
|
|
1021
|
+
|
836
|
1022
|
/* Get buffer size */
|
837
|
1023
|
get_real ( bufsize, ix86->segs.ds,
|
838
|
1024
|
( ix86->regs.si + offsetof ( typeof ( addr ), bufsize ) ) );
|
|
@@ -1300,26 +1486,29 @@ static void int13_hook_vector ( void ) {
|
1300
|
1486
|
"popw 6(%%bp)\n\t"
|
1301
|
1487
|
/* Fix up %dl:
|
1302
|
1488
|
*
|
1303
|
|
- * INT 13,15 : do nothing
|
|
1489
|
+ * INT 13,15 : do nothing if hard disk
|
1304
|
1490
|
* INT 13,08 : load with number of drives
|
1305
|
1491
|
* all others: restore original value
|
1306
|
1492
|
*/
|
1307
|
1493
|
"cmpb $0x15, -1(%%bp)\n\t"
|
1308
|
|
- "je 2f\n\t"
|
|
1494
|
+ "jne 2f\n\t"
|
|
1495
|
+ "testb $0x80, -4(%%bp)\n\t"
|
|
1496
|
+ "jnz 3f\n\t"
|
|
1497
|
+ "\n2:\n\t"
|
1309
|
1498
|
"movb -4(%%bp), %%dl\n\t"
|
1310
|
1499
|
"cmpb $0x08, -1(%%bp)\n\t"
|
1311
|
|
- "jne 2f\n\t"
|
1312
|
|
- "pushw %%ds\n\t"
|
1313
|
|
- "pushw %1\n\t"
|
1314
|
|
- "popw %%ds\n\t"
|
1315
|
|
- "movb %c2, %%dl\n\t"
|
1316
|
|
- "popw %%ds\n\t"
|
|
1500
|
+ "jne 3f\n\t"
|
|
1501
|
+ "testb $0x80, %%dl\n\t"
|
|
1502
|
+ "movb %%cs:%c1, %%dl\n\t"
|
|
1503
|
+ "jnz 3f\n\t"
|
|
1504
|
+ "movb %%cs:%c2, %%dl\n\t"
|
1317
|
1505
|
/* Return */
|
1318
|
|
- "\n2:\n\t"
|
|
1506
|
+ "\n3:\n\t"
|
1319
|
1507
|
"movw %%bp, %%sp\n\t"
|
1320
|
1508
|
"popw %%bp\n\t"
|
1321
|
1509
|
"iret\n\t" )
|
1322
|
|
- : : "i" ( int13 ), "i" ( BDA_SEG ), "i" ( BDA_NUM_DRIVES ) );
|
|
1510
|
+ : : "i" ( int13 ), "i" ( __from_text16 ( &num_drives ) ),
|
|
1511
|
+ "i" ( __from_text16 ( &num_fdds ) ) );
|
1323
|
1512
|
|
1324
|
1513
|
hook_bios_interrupt ( 0x13, ( unsigned int ) int13_wrapper,
|
1325
|
1514
|
&int13_vector );
|
|
@@ -1404,14 +1593,13 @@ static void int13_free ( struct refcnt *refcnt ) {
|
1404
|
1593
|
*/
|
1405
|
1594
|
static int int13_hook ( struct uri *uri, unsigned int drive ) {
|
1406
|
1595
|
struct int13_drive *int13;
|
1407
|
|
- uint8_t num_drives;
|
1408
|
1596
|
unsigned int natural_drive;
|
1409
|
1597
|
void *scratch;
|
1410
|
1598
|
int rc;
|
1411
|
1599
|
|
1412
|
1600
|
/* Calculate natural drive number */
|
1413
|
|
- get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
|
1414
|
|
- natural_drive = ( num_drives | 0x80 );
|
|
1601
|
+ int13_sync_num_drives();
|
|
1602
|
+ natural_drive = ( ( drive & 0x80 ) ? ( num_drives | 0x80 ) : num_fdds );
|
1415
|
1603
|
|
1416
|
1604
|
/* Check that drive number is not in use */
|
1417
|
1605
|
list_for_each_entry ( int13, &int13s, list ) {
|
|
@@ -1468,7 +1656,7 @@ static int int13_hook ( struct uri *uri, unsigned int drive ) {
|
1468
|
1656
|
list_add ( &int13->list, &int13s );
|
1469
|
1657
|
|
1470
|
1658
|
/* Update BIOS drive count */
|
1471
|
|
- int13_set_num_drives();
|
|
1659
|
+ int13_sync_num_drives();
|
1472
|
1660
|
|
1473
|
1661
|
free ( scratch );
|
1474
|
1662
|
return 0;
|