- patch is checked in and there are no bugreports

This commit is contained in:
Volker Ruppert 2002-01-13 17:05:29 +00:00
parent 26a2731a19
commit c24eaf3e3c
2 changed files with 0 additions and 798 deletions

View File

@ -1,512 +0,0 @@
----------------------------------------------------------------------
Patch name: patch.floppy-volker
Author: Volker.Ruppert@t-online.de
Date: Don Dez 27 10:23:47 CET 2001
Detailed description:
This patch fixes the behaviour of some floppy commands (Windows 95 driver
works now). The changes are checked in, so you can use this file to revert
them if they cause trouble.
* diskette controller data register returns last result if no new data
is available
* reset will be activated when the reset bit is changed to normal operation
* reset sets the error bits in status register 0
* write access to port 0x3f4 will cause a BX_ERROR now
* unsupported and invalid floppy commands are setting the error status bit
'invalid command' - BX_PANIC not necessary
* flag FS_MS_DIO is not set while a floppy command is pending
* floppy command 'specify': cause a BX_ERROR when non-DMA mode is selected
* floppy command 'sense interrupt status' returns an error if no interrupt
is pending
* floppy command 'read ID' sets the 'busy' flag and returns no data if the
motor is not on
* removed SIMX86 section (not defined in bochs)
* define variable 'sTemp' for win32 only
* removed commented BX_INFO statements
Patch was created with:
diff -u
Apply patch to what version:
cvs checked out on DATE
Instructions:
To patch, go to main bochs directory.
Type "patch -p0 < THIS_PATCH_FILE".
----------------------------------------------------------------------
--- ../bochs/iodev/floppy.h Wed Oct 3 15:10:38 2001
+++ iodev/floppy.h Thu Dec 27 09:31:46 2001
@@ -70,6 +70,8 @@
Boolean command_complete;
Bit8u pending_command;
+ Boolean pending_irq;
+
Bit8u result[10];
Bit8u result_index;
Bit8u result_size;
--- ../bochs/iodev/floppy.cc Sun Oct 7 05:28:45 2001
+++ iodev/floppy.cc Thu Dec 27 09:38:45 2001
@@ -132,7 +132,7 @@
cmos->s.reg[0x10] = (cmos->s.reg[0x10] & 0x0f) | 0x50;
break;
default:
- BX_PANIC(( "unknown floppya type" ));
+ BX_PANIC(("unknown floppya type"));
}
if (bx_options.floppya.Otype->get () != BX_FLOPPY_NONE) {
@@ -226,6 +226,8 @@
BX_FD_THIS s.command_size = 0;
BX_FD_THIS s.pending_command = 0;
+ BX_FD_THIS s.pending_irq = 0;
+
BX_FD_THIS s.result_index = 0;
BX_FD_THIS s.result_size = 0;
@@ -307,13 +309,17 @@
case 0x3F5: /* diskette controller data */
if (BX_FD_THIS s.result_size == 0) {
- BX_PANIC(("diskette controller:port3f5: no results to read"));
+ BX_ERROR(("port 0x3f5: no results to read"));
+ BX_FD_THIS s.main_status_reg = 0;
+ return BX_FD_THIS s.result[0];
}
value = BX_FD_THIS s.result[BX_FD_THIS s.result_index++];
+ BX_FD_THIS s.main_status_reg &= 0xF0;
if (BX_FD_THIS s.result_index >= BX_FD_THIS s.result_size) {
BX_FD_THIS s.result_size = 0;
BX_FD_THIS s.result_index = 0;
+ BX_FD_THIS s.result[0] = value;
BX_FD_THIS s.main_status_reg = FD_MS_MRQ;
}
return(value);
@@ -399,22 +405,14 @@
if (prev_normal_operation==0 && normal_operation) {
// transition from RESET to NORMAL
-#if 0
-
- BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
- BX_FD_THIS s.pending_command = 0xfe; // RESET pending
-
bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index,
bx_options.Ofloppy_command_delay->get (), 0 );
-#endif
}
else if (prev_normal_operation && normal_operation==0) {
// transition from NORMAL to RESET
BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
BX_FD_THIS s.pending_command = 0xfe; // RESET pending
- bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index,
- bx_options.Ofloppy_command_delay->get (), 0 );
}
BX_DEBUG(("io_write: digital output register"));
BX_DEBUG((" motor on, drive1 = %d", motor_on_drive1 > 0));
@@ -431,7 +429,7 @@
break;
case 0x3f4: /* diskette controller data rate select register */
- BX_PANIC(("io_write: data rate select register"));
+ BX_ERROR(("io_write: data rate select register unsupported"));
break;
case 0x3F5: /* diskette controller data */
@@ -457,8 +455,6 @@
break;
case 0x08: /* sense interrupt status */
BX_FD_THIS s.command_size = 1;
- floppy_command();
- BX_FD_THIS s.command_complete = 1;
break;
case 0x0f: /* seek */
BX_FD_THIS s.command_size = 3;
@@ -483,29 +479,29 @@
// These commands are not implemented on the standard
// controller and return an error. They are available on
// the enhanced controller.
+ BX_DEBUG(("io_write: 0x3f5: unsupported floppy command 0x%02x",
+ (unsigned) value));
BX_FD_THIS s.command_size = 1;
- BX_FD_THIS s.result[0] = 0x80;
- BX_FD_THIS s.result_size = 1;
- BX_FD_THIS s.result_index = 0;
- BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
- BX_FD_THIS s.command_complete = 1;
+ BX_FD_THIS s.status_reg0 = 0x80; // status: invalid command
break;
default:
- BX_PANIC(("io write:3f5: unsupported case 0x%02x",
+ BX_ERROR(("io_write: 0x3f5: invalid floppy command 0x%02x",
(unsigned) value));
+ BX_FD_THIS s.command_size = 1;
+ BX_FD_THIS s.status_reg0 = 0x80; // status: invalid command
break;
}
}
else {
BX_FD_THIS s.command[BX_FD_THIS s.command_index++] =
value;
- if (BX_FD_THIS s.command_index ==
- BX_FD_THIS s.command_size) {
- /* read/write command not in progress any more */
- floppy_command();
- BX_FD_THIS s.command_complete = 1;
- }
+ }
+ if (BX_FD_THIS s.command_index ==
+ BX_FD_THIS s.command_size) {
+ /* read/write command not in progress any more */
+ floppy_command();
+ BX_FD_THIS s.command_complete = 1;
}
BX_DEBUG(("io_write: diskette controller data"));
return;
@@ -568,12 +564,13 @@
switch (BX_FD_THIS s.command[0]) {
case 0x03: // specify
-//BX_INFO(("floppy_command specify"));
// execution: specified parameters are loaded
// result: no result bytes, no interrupt
step_rate_time = BX_FD_THIS s.command[1] >> 4;
head_unload_time = BX_FD_THIS s.command[1] & 0x0f;
head_load_time = BX_FD_THIS s.command[2] >> 1;
+ if (BX_FD_THIS s.command[2] & 0x01)
+ BX_ERROR(("non DMA mode selected"));
BX_FD_THIS s.main_status_reg = FD_MS_MRQ;
return;
break;
@@ -589,7 +586,6 @@
break;
case 0x07: // recalibrate
-//BX_INFO(("floppy_command recalibrate"));
drive = (BX_FD_THIS s.command[1] & 0x03);
BX_FD_THIS s.DOR &= 0xfc;
BX_FD_THIS s.DOR |= drive;
@@ -616,13 +612,12 @@
* seek end bit set to 1 in Status reg 0 regardless of outcome
*/
/* data reg not ready, controller busy */
- BX_FD_THIS s.main_status_reg = FD_MS_DIO | FD_MS_BUSY;
+ BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
BX_FD_THIS s.pending_command = 0x07; // recalibrate pending
return;
break;
case 0x08: /* sense interrupt status */
-//BX_INFO(("floppy_command sense interrupt status"));
/* execution:
* get status
* result:
@@ -630,21 +625,27 @@
* byte0 = status reg0
* byte1 = current cylinder number (0 to 79)
*/
- /*BX_FD_THIS s.status_reg0 = ;*/
drive = BX_FD_THIS s.DOR & 0x03;
- BX_FD_THIS s.result[0] = 0x20 | drive;
+ if (BX_FD_THIS s.pending_irq) {
+ BX_FD_THIS s.pending_irq = 0;
+ }
+ else {
+ BX_FD_THIS s.status_reg0 = 0x80;
+ }
+ BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
BX_FD_THIS s.result[1] = BX_FD_THIS s.cylinder[drive];
BX_FD_THIS s.result_size = 2;
BX_FD_THIS s.result_index = 0;
+ BX_FD_THIS s.status_reg0 = 0;
/* read ready */
- BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
+ BX_FD_THIS s.main_status_reg &= 0x0f;
+ BX_FD_THIS s.main_status_reg |= (FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY);
BX_DEBUG(("sense interrupt status"));
return;
break;
case 0x0f: /* seek */
-//BX_INFO(("floppy_command seek"));
/* command:
* byte0 = 0F
* byte1 = drive & head select
@@ -666,7 +667,7 @@
bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index,
bx_options.Ofloppy_command_delay->get (), 0 );
/* data reg not ready, controller busy */
- BX_FD_THIS s.main_status_reg = FD_MS_DIO | FD_MS_BUSY;
+ BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
BX_FD_THIS s.pending_command = 0x0f; /* seek pending */
return;
break;
@@ -682,38 +683,38 @@
break;
case 0x4a: // read ID
-//BX_INFO(("floppy_command read ID")); // ???
drive = BX_FD_THIS s.command[1] & 0x03;
BX_FD_THIS s.DOR &= 0xfc;
BX_FD_THIS s.DOR |= drive;
motor_on = (BX_FD_THIS s.DOR>>(drive+4)) & 0x01;
- if (motor_on == 0)
- BX_PANIC(("floppy_command(): 4a: motor not on"));
+ if (motor_on == 0) {
+ BX_ERROR(("floppy_command(): 0x4a: motor not on"));
+ BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
+ return;
+ }
if (drive > 1)
BX_PANIC(("io: 4a: bad drive #"));
BX_FD_THIS s.result_size = 7;
BX_FD_THIS s.result_index = 0;
- BX_FD_THIS s.result[0] = 0; /* ??? */
- BX_FD_THIS s.result[1] = 0;
- BX_FD_THIS s.result[2] = 0;
+ // setting result[0] in timer handler
+ BX_FD_THIS s.result[1] = BX_FD_THIS s.status_reg1;
+ BX_FD_THIS s.result[2] = BX_FD_THIS s.status_reg2;
BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive];
- BX_FD_THIS s.result[4] = 0; /* head */
- BX_FD_THIS s.result[5] = 0; /* sector at completion */
- BX_FD_THIS s.result[6] = 2;
+ BX_FD_THIS s.result[4] = BX_FD_THIS s.head[drive];
+ BX_FD_THIS s.result[5] = 1; /* sector at completion */
+ BX_FD_THIS s.result[6] = 2; // sector size code
bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index,
bx_options.Ofloppy_command_delay->get (), 0 );
/* data reg not ready, controller busy */
- BX_FD_THIS s.main_status_reg = FD_MS_DIO | FD_MS_BUSY;
+ BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
BX_FD_THIS s.pending_command = 0x4a; /* read ID pending */
return;
break;
case 0xe6: // read normal data
-//BX_INFO(("floppy_command read normal data"));
case 0xc5: // write normal data
-//BX_INFO(("floppy_command write normal data"));
if ( (BX_FD_THIS s.DOR & 0x08) == 0 )
BX_PANIC(("read/write command with DMA and int disabled"));
drive = BX_FD_THIS s.command[1] & 0x03;
@@ -749,7 +750,8 @@
BX_ERROR(("head number in command[1] doesn't match head field"));
BX_FD_THIS s.result_size = 7;
BX_FD_THIS s.result_index = 0;
- BX_FD_THIS s.result[0] = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive; // abnormal termination
+ BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive; // abnormal termination
+ BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
BX_FD_THIS s.result[1] = 0x04; // 0000 0100
BX_FD_THIS s.result[2] = 0x00; // 0000 0000
BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive];
@@ -760,6 +762,7 @@
BX_FD_THIS s.pending_command = 0;
BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
BX_FD_THIS devices->pic->trigger_irq(6);
+ BX_FD_THIS s.pending_irq = 1;
return;
}
@@ -771,7 +774,8 @@
(unsigned) BX_FD_THIS s.media[drive].sectors_per_track));
BX_FD_THIS s.result_size = 7;
BX_FD_THIS s.result_index = 0;
- BX_FD_THIS s.result[0] = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive; // abnormal termination
+ BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive; // abnormal termination
+ BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
BX_FD_THIS s.result[1] = 0x25; // 0010 0101
BX_FD_THIS s.result[2] = 0x31; // 0011 0001
BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive];
@@ -782,6 +786,7 @@
BX_FD_THIS s.pending_command = 0;
BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
BX_FD_THIS devices->pic->trigger_irq(6);
+ BX_FD_THIS s.pending_irq = 1;
return;
}
@@ -810,7 +815,8 @@
BX_FD_THIS s.result_index = 0;
// 0100 0HDD abnormal termination
- BX_FD_THIS s.result[0] = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive;
+ BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive;
+ BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
// 1000 0101 end of cyl/NDAT/NID
BX_FD_THIS s.result[1] = 0x86;
// 0000 0000
@@ -823,7 +829,7 @@
bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index,
bx_options.Ofloppy_command_delay->get (), 0 );
/* data reg not ready, controller busy */
- BX_FD_THIS s.main_status_reg = FD_MS_DIO | FD_MS_BUSY;
+ BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
BX_FD_THIS s.pending_command = BX_FD_THIS s.command[0];
return;
}
@@ -856,7 +862,7 @@
bx_pc_system.set_DRQ(FLOPPY_DMA_CHAN, 1);
/* data reg not ready, controller busy */
- BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
+ BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
BX_FD_THIS s.pending_command = BX_FD_THIS s.command[0];
return;
}
@@ -866,7 +872,7 @@
bx_pc_system.set_DRQ(FLOPPY_DMA_CHAN, 1);
/* data reg not ready, controller busy */
- BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
+ BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
BX_FD_THIS s.pending_command = BX_FD_THIS s.command[0];
return;
}
@@ -876,10 +882,13 @@
return;
break;
- default:
- BX_PANIC(("floppy_command(): unknown function"));
+ default: // invalid or unsupported command
+ BX_FD_THIS s.result_size = 1;
+ BX_FD_THIS s.result_index = 0;
+ BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
+ BX_FD_THIS s.status_reg0 = 0;
+ BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
}
- BX_PANIC(("floppy_command()"));
#endif
}
@@ -949,9 +958,6 @@
void
bx_floppy_ctrl_c::timer_handler(void *this_ptr)
{
-#if defined(SIMX86)
- printf("Floppy timer");
-#endif
bx_floppy_ctrl_c *class_ptr = (bx_floppy_ctrl_c *) this_ptr;
@@ -961,38 +967,56 @@
void
bx_floppy_ctrl_c::timer()
{
+ Bit8u drive;
+
+ drive = BX_FD_THIS s.DOR & 0x03;
switch ( BX_FD_THIS s.pending_command ) {
case 0x07: // recal
BX_FD_THIS s.pending_command = 0;
/* write ready, not busy */
- BX_FD_THIS s.main_status_reg = FD_MS_MRQ;
+ BX_FD_THIS s.main_status_reg = FD_MS_MRQ | (1 << drive);
+ BX_FD_THIS s.status_reg0 = 0x20 | drive;
BX_FD_THIS devices->pic->trigger_irq(6);
+ BX_FD_THIS s.pending_irq = 1;
goto reset_changeline;
break;
case 0x0f: // seek
BX_FD_THIS s.pending_command = 0;
/* write ready, not busy */
- BX_FD_THIS s.main_status_reg = FD_MS_MRQ;
+ BX_FD_THIS s.main_status_reg = FD_MS_MRQ | (1 << drive);
+ BX_FD_THIS s.status_reg0 = 0x20 | drive;
BX_FD_THIS devices->pic->trigger_irq(6);
+ BX_FD_THIS s.pending_irq = 1;
goto reset_changeline;
break;
-
case 0x4a: /* read ID */
+ BX_FD_THIS s.pending_command = 0;
+ /* read ready, busy */
+ BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO;
+ BX_FD_THIS s.status_reg0 = 0x20 | drive;
+ BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
+ BX_FD_THIS devices->pic->trigger_irq(6);
+ BX_FD_THIS s.pending_irq = 1;
+ break;
+
case 0xc5: // write normal data
case 0xe6: // read normal data
BX_FD_THIS s.pending_command = 0;
/* read ready, busy */
- BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO;
+ BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | (1 << drive);
+ BX_FD_THIS s.status_reg0 = 0x20 | drive;
BX_FD_THIS devices->pic->trigger_irq(6);
+ BX_FD_THIS s.pending_irq = 1;
break;
case 0xfe: // (contrived) RESET
reset(BX_RESET_SOFTWARE);
BX_FD_THIS s.pending_command = 0;
- BX_FD_THIS s.main_status_reg = FD_MS_MRQ;
+ BX_FD_THIS s.status_reg0 = 0xc0;
BX_FD_THIS devices->pic->trigger_irq(6);
+ BX_FD_THIS s.pending_irq = 1;
break;
default:
@@ -1002,7 +1026,6 @@
return;
reset_changeline:
- unsigned drive = BX_FD_THIS s.DOR & 0x3;
if (drive > 1) return;
if (BX_FD_THIS s.media_present[drive])
BX_FD_THIS s.DIR &= ~0x80; // clear disk change line
@@ -1026,10 +1049,11 @@
BX_FD_THIS s.floppy_buffer_index = 0;
if (bx_pc_system.TC) { // Terminal Count line, done
BX_FD_THIS s.pending_command = 0;
- BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
+ BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY | (1 << drive);
BX_FD_THIS s.result_size = 7;
BX_FD_THIS s.result_index = 0;
- BX_FD_THIS s.result[0] = (BX_FD_THIS s.head[drive] << 2) | drive;
+ BX_FD_THIS s.status_reg0 = 0x20 | (BX_FD_THIS s.head[drive] << 2) | drive;
+ BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
BX_FD_THIS s.result[1] = 0;
BX_FD_THIS s.result[2] = 0;
BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive];
@@ -1096,7 +1120,7 @@
BX_FD_THIS s.result[6] = 2; // sector size = 512
BX_FD_THIS s.pending_command = 0;
- BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
+ BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY | (1 << drive);
BX_FD_THIS devices->pic->trigger_irq(6);
return;
}
@@ -1109,7 +1133,8 @@
BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
BX_FD_THIS s.result_size = 7;
BX_FD_THIS s.result_index = 0;
- BX_FD_THIS s.result[0] = (BX_FD_THIS s.head[drive] << 2) | drive;
+ BX_FD_THIS s.status_reg0 = 0x20 | (BX_FD_THIS s.head[drive] << 2) | drive;
+ BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
BX_FD_THIS s.result[1] = 0;
BX_FD_THIS s.result[2] = 0;
BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive];
@@ -1222,7 +1247,9 @@
{
struct stat stat_buf;
int ret;
+#if BX_WITH_WIN32
char sTemp[1024];
+#endif
if (type == BX_FLOPPY_NONE)
return(0);

View File

@ -1,286 +0,0 @@
----------------------------------------------------------------------
Patch name: patch.floppy-volker
Author: Volker.Ruppert@t-online.de
Date: Don Dez 28 17:29:00 CET 2001
Detailed description:
This patch contains the second set of changes to bochs floppy support.
The changes are checked in, so you can use this file to revert them if
they cause trouble.
* floppy command 'format track' implemented
* read and write operations with MT=0 are working now
(function 'increment_sector()' updated)
* result code of floppy command 'get status' fixed
* flag FS_MS_DIO is not set while the 'configure' floppy command is pending
Patch was created with:
diff -u
Apply patch to what version:
cvs checked out on DATE
Instructions:
To patch, go to main bochs directory.
Type "patch -p0 < THIS_PATCH_FILE".
----------------------------------------------------------------------
--- ../bochs/iodev/floppy.cc Thu Dec 27 10:30:31 2001
+++ iodev/floppy.cc Fri Dec 28 17:06:26 2001
@@ -462,9 +462,14 @@
case 0x4a: /* read ID */
BX_FD_THIS s.command_size = 2;
break;
+ case 0x4d: /* format track */
+ BX_FD_THIS s.command_size = 6;
+ break;
+ case 0x45:
case 0xc5: /* write normal data */
BX_FD_THIS s.command_size = 9;
break;
+ case 0x66:
case 0xe6: /* read normal data */
BX_FD_THIS s.command_size = 9;
break;
@@ -577,8 +582,8 @@
case 0x04: // get status
drive = (BX_FD_THIS s.command[1] & 0x03);
- BX_FD_THIS s.result[0] =
- BX_FD_THIS s.media[drive].write_protected ? 0x40 : 0x00;
+ BX_FD_THIS s.result[0] = 0x28 | (BX_FD_THIS s.head[drive]<<2) | drive
+ | (BX_FD_THIS s.media[drive].write_protected ? 0x40 : 0x00);
BX_FD_THIS s.result_size = 1;
BX_FD_THIS s.result_index = 0;
BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
@@ -678,7 +683,7 @@
BX_FD_THIS s.result_size = 0;
BX_FD_THIS s.result_index = 0;
BX_FD_THIS s.pending_command = 0;
- BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
+ BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_BUSY;
return;
break;
@@ -712,9 +717,77 @@
return;
break;
+ case 0x4d: // format track
+ drive = BX_FD_THIS s.command[1] & 0x03;
+ BX_FD_THIS s.DOR &= 0xfc;
+ BX_FD_THIS s.DOR |= drive;
+
+ motor_on = (BX_FD_THIS s.DOR>>(drive+4)) & 0x01;
+ if (motor_on == 0)
+ BX_PANIC(("floppy_command(): format track: motor not on"));
+ BX_FD_THIS s.head[drive] = (BX_FD_THIS s.command[1] >> 2) & 0x01;
+ sector_size = BX_FD_THIS s.command[2];
+ BX_FD_THIS s.format_count = BX_FD_THIS s.command[3];
+ BX_FD_THIS s.format_fillbyte = BX_FD_THIS s.command[5];
+ if (drive > 1)
+ BX_PANIC(("format track: bad drive #%d", drive));
+
+ if (sector_size != 0x02) { // 512 bytes
+ BX_PANIC(("format track: sector_size not 512"));
+ }
+ if (BX_FD_THIS s.format_count != BX_FD_THIS s.media[drive].sectors_per_track) {
+ BX_PANIC(("format track: wrong number of sectors/track"));
+ }
+ if ( BX_FD_THIS s.media_present[drive] == 0 ) {
+ // media not in drive, return error
+ BX_INFO(("attempt to format track with media not present"));
+ BX_FD_THIS s.result_size = 7;
+ BX_FD_THIS s.result_index = 0;
+ BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive; // abnormal termination
+ BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
+ BX_FD_THIS s.result[1] = 0x25; // 0010 0101
+ BX_FD_THIS s.result[2] = 0x31; // 0011 0001
+ // 4 result bytes are unused
+ BX_FD_THIS s.pending_command = 0;
+ BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
+ BX_FD_THIS devices->pic->trigger_irq(6);
+ BX_FD_THIS s.pending_irq = 1;
+ return;
+ }
+ if (BX_FD_THIS s.media[drive].write_protected) {
+ // media write-protected, return error
+ BX_INFO(("attempt to format track with media write-protected"));
+ BX_FD_THIS s.result_size = 7;
+ BX_FD_THIS s.result_index = 0;
+ BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive; // abnormal termination
+ BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
+ BX_FD_THIS s.result[1] = 0x27; // 0010 0111
+ BX_FD_THIS s.result[2] = 0x31; // 0011 0001
+ // 4 result bytes are unused
+ BX_FD_THIS s.pending_command = 0;
+ BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
+ BX_FD_THIS devices->pic->trigger_irq(6);
+ BX_FD_THIS s.pending_irq = 1;
+ return;
+ }
+
+ /* 4 header bytes per sector are required */
+ BX_FD_THIS s.format_count <<= 2;
- case 0xe6: // read normal data
- case 0xc5: // write normal data
+ bx_pc_system.set_DRQ(FLOPPY_DMA_CHAN, 1);
+
+ /* data reg not ready, controller busy */
+ BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
+ BX_FD_THIS s.pending_command = 0x4d; /* format track pending */
+ BX_DEBUG(("format track"));
+ return;
+ break;
+
+ case 0x66: // read normal data, MT=0
+ case 0xe6: // read normal data, MT=1
+ case 0x45: // write normal data, MT=0
+ case 0xc5: // write normal data, MT=1
+ BX_FD_THIS s.multi_track = (BX_FD_THIS s.command[0] >> 7);
if ( (BX_FD_THIS s.DOR & 0x08) == 0 )
BX_PANIC(("read/write command with DMA and int disabled"));
drive = BX_FD_THIS s.command[1] & 0x03;
@@ -744,7 +817,7 @@
// check that head number in command[1] bit two matches the head
// reported in the head number field. Real floppy drives are
- // picky about this, as reported in SF bug #439945, (Floppy drive
+ // picky about this, as reported in SF bug #439945, (Floppy drive
// read input error checking).
if (head != (BX_FD_THIS s.command[1]>>2)&1) {
BX_ERROR(("head number in command[1] doesn't match head field"));
@@ -854,7 +927,7 @@
BX_FD_THIS s.sector[drive] = sector;
BX_FD_THIS s.head[drive] = head;
- if (BX_FD_THIS s.command[0] == 0xe6) { // read
+ if ((BX_FD_THIS s.command[0] & 0x7f) == 0x66) { // read
floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer,
512, FROM_FLOPPY);
BX_FD_THIS s.floppy_buffer_index = 0;
@@ -866,7 +939,7 @@
BX_FD_THIS s.pending_command = BX_FD_THIS s.command[0];
return;
}
- else if (BX_FD_THIS s.command[0] == 0xc5) { // write
+ else if ((BX_FD_THIS s.command[0] & 0x7f) == 0x45) { // write
BX_FD_THIS s.floppy_buffer_index = 0;
bx_pc_system.set_DRQ(FLOPPY_DMA_CHAN, 1);
@@ -1001,8 +1074,10 @@
BX_FD_THIS s.pending_irq = 1;
break;
- case 0xc5: // write normal data
- case 0xe6: // read normal data
+ case 0x66: // read normal data
+ case 0xe6:
+ case 0x45: // write normal data
+ case 0xc5:
BX_FD_THIS s.pending_command = 0;
/* read ready, busy */
BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | (1 << drive);
@@ -1096,10 +1171,56 @@
Bit8u drive;
Bit32u logical_sector;
+ drive = BX_FD_THIS s.DOR & 0x03;
+ if (BX_FD_THIS s.pending_command == 0x4d) { // format track in progress
+ --BX_FD_THIS s.format_count;
+ switch (3 - (BX_FD_THIS s.format_count & 0x03)) {
+ case 0:
+ BX_FD_THIS s.cylinder[drive] = *data_byte;
+ break;
+ case 1:
+ if (*data_byte != BX_FD_THIS s.head[drive])
+ BX_ERROR(("head number does not match head field"));
+ break;
+ case 2:
+ BX_FD_THIS s.sector[drive] = *data_byte;
+ break;
+ case 3:
+ if (*data_byte != 2) BX_ERROR(("sector size code not 2"));
+ BX_DEBUG(("formatting cylinder %u head %u sector %u",
+ BX_FD_THIS s.cylinder[drive], BX_FD_THIS s.head[drive],
+ BX_FD_THIS s.sector[drive]));
+ for (unsigned i = 0; i < 512; i++) {
+ BX_FD_THIS s.floppy_buffer[i] = BX_FD_THIS s.format_fillbyte;
+ }
+ logical_sector = (BX_FD_THIS s.cylinder[drive] * 2 * BX_FD_THIS s.media[drive].sectors_per_track) +
+ (BX_FD_THIS s.head[drive] * BX_FD_THIS s.media[drive].sectors_per_track) +
+ (BX_FD_THIS s.sector[drive] - 1);
+ floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer,
+ 512, TO_FLOPPY);
+ break;
+ }
+ if ((BX_FD_THIS s.format_count == 0) || (bx_pc_system.TC)) {
+ BX_FD_THIS s.format_count = 0;
+ BX_FD_THIS s.pending_command = 0;
+ BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY | (1 << drive);
+ BX_FD_THIS s.result_size = 7;
+ BX_FD_THIS s.result_index = 0;
+ BX_FD_THIS s.status_reg0 = (BX_FD_THIS s.head[drive] << 2) | drive;
+ BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
+ BX_FD_THIS s.result[1] = BX_FD_THIS s.status_reg1;
+ BX_FD_THIS s.result[2] = BX_FD_THIS s.status_reg2;
+ // 4 result bytes are unused
+ BX_FD_THIS devices->pic->trigger_irq(6);
+ BX_FD_THIS s.pending_irq = 1;
+ bx_pc_system.set_DRQ(FLOPPY_DMA_CHAN, 0);
+ }
+ return;
+ }
+
BX_FD_THIS s.floppy_buffer[BX_FD_THIS s.floppy_buffer_index++] = *data_byte;
if (BX_FD_THIS s.floppy_buffer_index >= 512) {
- drive = BX_FD_THIS s.DOR & 0x03;
logical_sector = (BX_FD_THIS s.cylinder[drive] * 2 * BX_FD_THIS s.media[drive].sectors_per_track) +
(BX_FD_THIS s.head[drive] * BX_FD_THIS s.media[drive].sectors_per_track) +
(BX_FD_THIS s.sector[drive] - 1);
@@ -1171,17 +1292,22 @@
// ??? calculation depends on base_count being multiple of 512
BX_FD_THIS s.sector[drive] ++;
if (BX_FD_THIS s.sector[drive] > BX_FD_THIS s.media[drive].sectors_per_track) {
- BX_FD_THIS s.sector[drive] -= BX_FD_THIS s.media[drive].sectors_per_track;
- BX_FD_THIS s.head[drive] ++;
- if (BX_FD_THIS s.head[drive] > 1) {
- BX_FD_THIS s.head[drive] = 0;
- BX_FD_THIS s.cylinder[drive] ++;
- if (BX_FD_THIS s.cylinder[drive] >= BX_FD_THIS s.media[drive].tracks) {
- // Set to 1 past last possible cylinder value.
- // I notice if I set it to tracks-1, prama linux won't boot.
- BX_FD_THIS s.cylinder[drive] = BX_FD_THIS s.media[drive].tracks;
- BX_INFO(("increment_sector: clamping cylinder to max"));
+ BX_FD_THIS s.sector[drive] = 1;
+ if (BX_FD_THIS s.multi_track) {
+ BX_FD_THIS s.head[drive] ++;
+ if (BX_FD_THIS s.head[drive] > 1) {
+ BX_FD_THIS s.head[drive] = 0;
+ BX_FD_THIS s.cylinder[drive] ++;
}
+ }
+ else {
+ BX_FD_THIS s.cylinder[drive] ++;
+ }
+ if (BX_FD_THIS s.cylinder[drive] >= BX_FD_THIS s.media[drive].tracks) {
+ // Set to 1 past last possible cylinder value.
+ // I notice if I set it to tracks-1, prama linux won't boot.
+ BX_FD_THIS s.cylinder[drive] = BX_FD_THIS s.media[drive].tracks;
+ BX_INFO(("increment_sector: clamping cylinder to max"));
}
}
}
--- ../bochs/iodev/floppy.h Thu Dec 27 10:28:53 2001
+++ iodev/floppy.h Fri Dec 28 13:59:47 2001
@@ -70,7 +70,10 @@
Boolean command_complete;
Bit8u pending_command;
+ Boolean multi_track;
Boolean pending_irq;
+ Bit8u format_count;
+ Bit8u format_fillbyte;
Bit8u result[10];
Bit8u result_index;