- floppy cleanup patch from Alex Thiel. New functions enter_idle_phase() and

enter_result_phase(). This patch does not add new features and should not
  break anything.
This commit is contained in:
Volker Ruppert 2002-11-30 09:39:29 +00:00
parent de6fa4e2c5
commit d05e7cc10c
2 changed files with 155 additions and 244 deletions

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: floppy.cc,v 1.57 2002-10-25 11:44:39 bdenney Exp $ // $Id: floppy.cc,v 1.58 2002-11-30 09:39:29 vruppert Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2002 MandrakeSoft S.A. // Copyright (C) 2002 MandrakeSoft S.A.
@ -101,7 +101,7 @@ bx_floppy_ctrl_c::init(void)
{ {
Bit8u i; Bit8u i;
BX_DEBUG(("Init $Id: floppy.cc,v 1.57 2002-10-25 11:44:39 bdenney Exp $")); BX_DEBUG(("Init $Id: floppy.cc,v 1.58 2002-11-30 09:39:29 vruppert Exp $"));
DEV_dma_register_8bit_channel(2, dma_read, dma_write, "Floppy Drive"); DEV_dma_register_8bit_channel(2, dma_read, dma_write, "Floppy Drive");
DEV_register_irq(6, "Floppy Drive"); DEV_register_irq(6, "Floppy Drive");
for (unsigned addr=0x03F2; addr<=0x03F7; addr++) { for (unsigned addr=0x03F2; addr<=0x03F7; addr++) {
@ -161,10 +161,10 @@ bx_floppy_ctrl_c::init(void)
& BX_FD_THIS s.media[0])) & BX_FD_THIS s.media[0]))
BX_FD_THIS s.media_present[0] = 1; BX_FD_THIS s.media_present[0] = 1;
else else
bx_options.floppya.Ostatus->set(BX_EJECTED); bx_options.floppya.Ostatus->set(BX_EJECTED);
#define MED (BX_FD_THIS s.media[0]) #define MED (BX_FD_THIS s.media[0])
BX_INFO(("fd0: '%s' ro=%d, h=%d,t=%d,spt=%d", bx_options.floppya.Opath->getptr(), BX_INFO(("fd0: '%s' ro=%d, h=%d,t=%d,spt=%d", bx_options.floppya.Opath->getptr(),
MED.write_protected, MED.heads, MED.tracks, MED.sectors_per_track)); MED.write_protected, MED.heads, MED.tracks, MED.sectors_per_track));
#undef MED #undef MED
} }
} }
@ -212,10 +212,10 @@ bx_floppy_ctrl_c::init(void)
& BX_FD_THIS s.media[1])) & BX_FD_THIS s.media[1]))
BX_FD_THIS s.media_present[1] = 1; BX_FD_THIS s.media_present[1] = 1;
else else
bx_options.floppyb.Ostatus->set(BX_EJECTED); bx_options.floppyb.Ostatus->set(BX_EJECTED);
#define MED (BX_FD_THIS s.media[1]) #define MED (BX_FD_THIS s.media[1])
BX_INFO(("fd1: '%s' ro=%d, h=%d,t=%d,spt=%d", bx_options.floppyb.Opath->getptr(), BX_INFO(("fd1: '%s' ro=%d, h=%d,t=%d,spt=%d", bx_options.floppyb.Opath->getptr(),
MED.write_protected, MED.heads, MED.tracks, MED.sectors_per_track)); MED.write_protected, MED.heads, MED.tracks, MED.sectors_per_track));
#undef MED #undef MED
} }
} }
@ -233,7 +233,7 @@ bx_floppy_ctrl_c::init(void)
if (BX_FD_THIS s.floppy_timer_index == BX_NULL_TIMER_HANDLE) { if (BX_FD_THIS s.floppy_timer_index == BX_NULL_TIMER_HANDLE) {
BX_FD_THIS s.floppy_timer_index = BX_FD_THIS s.floppy_timer_index =
bx_pc_system.register_timer( this, timer_handler, bx_pc_system.register_timer( this, timer_handler,
bx_options.Ofloppy_command_delay->get (), 0,0, "floppy"); bx_options.Ofloppy_command_delay->get (), 0,0, "floppy");
} }
BX_DEBUG(("bx_options.Ofloppy_command_delay = %u", BX_DEBUG(("bx_options.Ofloppy_command_delay = %u",
@ -247,19 +247,10 @@ bx_floppy_ctrl_c::reset(unsigned type)
{ {
Bit32u i; Bit32u i;
BX_FD_THIS s.command_complete = 1; /* waiting for new command */
BX_FD_THIS s.command_index = 0;
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.pending_irq = 0;
BX_FD_THIS s.reset_sensei = 0; /* no reset result present */ BX_FD_THIS s.reset_sensei = 0; /* no reset result present */
BX_FD_THIS s.result_index = 0; BX_FD_THIS s.main_status_reg = 0;
BX_FD_THIS s.result_size = 0;
/* data register ready, not in DMA mode */
BX_FD_THIS s.main_status_reg = FD_MS_MRQ;
BX_FD_THIS s.status_reg0 = 0; BX_FD_THIS s.status_reg0 = 0;
BX_FD_THIS s.status_reg1 = 0; BX_FD_THIS s.status_reg1 = 0;
BX_FD_THIS s.status_reg2 = 0; BX_FD_THIS s.status_reg2 = 0;
@ -286,10 +277,9 @@ bx_floppy_ctrl_c::reset(unsigned type)
BX_FD_THIS s.sector[i] = 0; BX_FD_THIS s.sector[i] = 0;
} }
BX_FD_THIS s.floppy_buffer_index = 0;
DEV_pic_lower_irq(6); DEV_pic_lower_irq(6);
DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0); DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0);
enter_idle_phase();
} }
@ -344,12 +334,9 @@ bx_floppy_ctrl_c::read(Bit32u address, unsigned io_len)
value = BX_FD_THIS s.result[BX_FD_THIS s.result_index++]; value = BX_FD_THIS s.result[BX_FD_THIS s.result_index++];
BX_FD_THIS s.main_status_reg &= 0xF0; BX_FD_THIS s.main_status_reg &= 0xF0;
if (BX_FD_THIS s.result_index >= BX_FD_THIS s.result_size) { 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;
if (!BX_FD_THIS s.reset_sensei) BX_FD_THIS s.pending_irq = 0; if (!BX_FD_THIS s.reset_sensei) BX_FD_THIS s.pending_irq = 0;
DEV_pic_lower_irq(6); DEV_pic_lower_irq(6);
enter_idle_phase();
} }
return(value); return(value);
break; break;
@ -360,12 +347,12 @@ bx_floppy_ctrl_c::read(Bit32u address, unsigned io_len)
switch( BX_FD_THIS s.DOR & 0x03 ) switch( BX_FD_THIS s.DOR & 0x03 )
{ {
case 0x00: case 0x00:
if( (BX_FD_THIS s.DOR & 0x10) == 0) break; if( (BX_FD_THIS s.DOR & 0x10) == 0) break;
return(2); return(2);
case 0x01: case 0x01:
if( (BX_FD_THIS s.DOR & 0x20) == 0) break; if( (BX_FD_THIS s.DOR & 0x20) == 0) break;
return(1); return(1);
} }
return(3); return(3);
@ -524,15 +511,17 @@ bx_floppy_ctrl_c::write(Bit32u address, Bit32u value, unsigned io_len)
// the enhanced controller. // the enhanced controller.
BX_DEBUG(("io_write: 0x3f5: unsupported floppy command 0x%02x", BX_DEBUG(("io_write: 0x3f5: unsupported floppy command 0x%02x",
(unsigned) value)); (unsigned) value));
BX_FD_THIS s.command_size = 1; BX_FD_THIS s.command_size = 0; // make sure we don't try to process this command
BX_FD_THIS s.status_reg0 = 0x80; // status: invalid command BX_FD_THIS s.status_reg0 = 0x80; // status: invalid command
enter_result_phase();
break; break;
default: default:
BX_ERROR(("io_write: 0x3f5: invalid floppy command 0x%02x", BX_ERROR(("io_write: 0x3f5: invalid floppy command 0x%02x",
(unsigned) value)); (unsigned) value));
BX_FD_THIS s.command_size = 1; BX_FD_THIS s.command_size = 0; // make sure we don't try to process this command
BX_FD_THIS s.status_reg0 = 0x80; // status: invalid command BX_FD_THIS s.status_reg0 = 0x80; // status: invalid command
enter_result_phase();
break; break;
} }
} }
@ -605,7 +594,8 @@ bx_floppy_ctrl_c::floppy_command(void)
BX_FD_THIS s.main_status_reg |= 20; BX_FD_THIS s.main_status_reg |= 20;
#endif #endif
switch (BX_FD_THIS s.command[0]) { BX_FD_THIS s.pending_command = BX_FD_THIS s.command[0];
switch (BX_FD_THIS s.pending_command) {
case 0x03: // specify case 0x03: // specify
// execution: specified parameters are loaded // execution: specified parameters are loaded
// result: no result bytes, no interrupt // result: no result bytes, no interrupt
@ -614,19 +604,17 @@ bx_floppy_ctrl_c::floppy_command(void)
head_load_time = BX_FD_THIS s.command[2] >> 1; head_load_time = BX_FD_THIS s.command[2] >> 1;
if (BX_FD_THIS s.command[2] & 0x01) if (BX_FD_THIS s.command[2] & 0x01)
BX_ERROR(("non DMA mode selected")); BX_ERROR(("non DMA mode selected"));
BX_FD_THIS s.main_status_reg = FD_MS_MRQ; enter_idle_phase();
return; return;
break; break;
case 0x04: // get status case 0x04: // get status
drive = (BX_FD_THIS s.command[1] & 0x03); drive = (BX_FD_THIS s.command[1] & 0x03);
BX_FD_THIS s.head[drive] = (BX_FD_THIS s.command[1] >> 2) & 0x01; BX_FD_THIS s.head[drive] = (BX_FD_THIS s.command[1] >> 2) & 0x01;
BX_FD_THIS s.result[0] = 0x28 | (BX_FD_THIS s.head[drive]<<2) | drive BX_FD_THIS s.status_reg3 = 0x28 | (BX_FD_THIS s.head[drive]<<2) | drive
| (BX_FD_THIS s.media[drive].write_protected ? 0x40 : 0x00); | (BX_FD_THIS s.media[drive].write_protected ? 0x40 : 0x00);
if (BX_FD_THIS s.cylinder[drive] == 0) BX_FD_THIS s.result[0] |= 0x10; if (BX_FD_THIS s.cylinder[drive] == 0) BX_FD_THIS s.status_reg3 |= 0x10;
BX_FD_THIS s.result_size = 1; enter_result_phase();
BX_FD_THIS s.result_index = 0;
BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
return; return;
break; break;
@ -651,10 +639,10 @@ bx_floppy_ctrl_c::floppy_command(void)
* controller set to non-busy * controller set to non-busy
* error condition noted in Status reg 0's equipment check bit * error condition noted in Status reg 0's equipment check bit
* seek end bit set to 1 in Status reg 0 regardless of outcome * seek end bit set to 1 in Status reg 0 regardless of outcome
* The last two are taken care of in timer().
*/ */
/* data reg not ready, drive busy */ BX_FD_THIS s.cylinder[drive] = 0;
BX_FD_THIS s.main_status_reg = (1 << drive); BX_FD_THIS s.main_status_reg = (1 << drive);
BX_FD_THIS s.pending_command = 0x07; // recalibrate pending
return; return;
break; break;
@ -669,7 +657,6 @@ bx_floppy_ctrl_c::floppy_command(void)
drive = BX_FD_THIS s.DOR & 0x03; drive = BX_FD_THIS s.DOR & 0x03;
if (!BX_FD_THIS s.pending_irq) { if (!BX_FD_THIS s.pending_irq) {
BX_FD_THIS s.status_reg0 = 0x80; BX_FD_THIS s.status_reg0 = 0x80;
BX_FD_THIS s.result_size = 1;
} }
else { else {
if (BX_FD_THIS s.reset_sensei > 0) { if (BX_FD_THIS s.reset_sensei > 0) {
@ -677,17 +664,11 @@ bx_floppy_ctrl_c::floppy_command(void)
BX_FD_THIS s.status_reg0 &= 0xf8; BX_FD_THIS s.status_reg0 &= 0xf8;
BX_FD_THIS s.status_reg0 |= (BX_FD_THIS s.head[drive] << 2) | drive; BX_FD_THIS s.status_reg0 |= (BX_FD_THIS s.head[drive] << 2) | drive;
BX_FD_THIS s.reset_sensei--; BX_FD_THIS s.reset_sensei--;
} }
BX_FD_THIS s.result[1] = BX_FD_THIS s.cylinder[drive];
BX_FD_THIS s.result_size = 2;
} }
BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
BX_FD_THIS s.result_index = 0;
/* read ready */
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")); BX_DEBUG(("sense interrupt status"));
enter_result_phase();
return; return;
break; break;
@ -712,7 +693,6 @@ bx_floppy_ctrl_c::floppy_command(void)
bx_options.Ofloppy_command_delay->get (), 0 ); bx_options.Ofloppy_command_delay->get (), 0 );
/* data reg not ready, drive busy */ /* data reg not ready, drive busy */
BX_FD_THIS s.main_status_reg = (1 << drive); BX_FD_THIS s.main_status_reg = (1 << drive);
BX_FD_THIS s.pending_command = 0x0f; /* seek pending */
return; return;
break; break;
@ -722,10 +702,7 @@ bx_floppy_ctrl_c::floppy_command(void)
BX_DEBUG(("configure (no poll = 0x%02x)", BX_FD_THIS s.command[2] & 0x10 )); BX_DEBUG(("configure (no poll = 0x%02x)", BX_FD_THIS s.command[2] & 0x10 ));
BX_DEBUG(("configure (fifothr = 0x%02x)", BX_FD_THIS s.command[2] & 0x0f )); BX_DEBUG(("configure (fifothr = 0x%02x)", BX_FD_THIS s.command[2] & 0x0f ));
BX_DEBUG(("configure (pretrk = 0x%02x)", BX_FD_THIS s.command[3] )); BX_DEBUG(("configure (pretrk = 0x%02x)", BX_FD_THIS s.command[3] ));
BX_FD_THIS s.result_size = 0; enter_idle_phase();
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_BUSY;
return; return;
break; break;
@ -743,20 +720,11 @@ bx_floppy_ctrl_c::floppy_command(void)
} }
if (BX_FD_THIS s.device_type[drive] == BX_FLOPPY_NONE) if (BX_FD_THIS s.device_type[drive] == BX_FLOPPY_NONE)
BX_PANIC(("floppy_command(): read ID: bad drive #%d", drive)); BX_PANIC(("floppy_command(): read ID: bad drive #%d", drive));
BX_FD_THIS s.result_size = 7; BX_FD_THIS s.status_reg0 = (BX_FD_THIS s.head[drive]<<2) | drive;
BX_FD_THIS s.result_index = 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] = 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_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index,
bx_options.Ofloppy_command_delay->get (), 0 ); bx_options.Ofloppy_command_delay->get (), 0 );
/* data reg not ready, controller busy */ /* data reg not ready, controller busy */
BX_FD_THIS s.main_status_reg = FD_MS_BUSY; BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
BX_FD_THIS s.pending_command = 0x4a; /* read ID pending */
return; return;
break; break;
@ -784,31 +752,19 @@ bx_floppy_ctrl_c::floppy_command(void)
if ( BX_FD_THIS s.media_present[drive] == 0 ) { if ( BX_FD_THIS s.media_present[drive] == 0 ) {
// media not in drive, return error // media not in drive, return error
BX_INFO(("attempt to format track with media not present")); 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.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.status_reg1 = 0x25; // 0010 0101
BX_FD_THIS s.result[1] = 0x25; // 0010 0101 BX_FD_THIS s.status_reg2 = 0x31; // 0011 0001
BX_FD_THIS s.result[2] = 0x31; // 0011 0001 enter_result_phase();
// 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;
raise_interrupt();
return; return;
} }
if (BX_FD_THIS s.media[drive].write_protected) { if (BX_FD_THIS s.media[drive].write_protected) {
// media write-protected, return error // media write-protected, return error
BX_INFO(("attempt to format track with media write-protected")); 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.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.status_reg1 = 0x27; // 0010 0111
BX_FD_THIS s.result[1] = 0x27; // 0010 0111 BX_FD_THIS s.status_reg2 = 0x31; // 0011 0001
BX_FD_THIS s.result[2] = 0x31; // 0011 0001 enter_result_phase();
// 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;
raise_interrupt();
return; return;
} }
@ -819,7 +775,6 @@ bx_floppy_ctrl_c::floppy_command(void)
/* data reg not ready, controller busy */ /* data reg not ready, controller busy */
BX_FD_THIS s.main_status_reg = FD_MS_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")); BX_DEBUG(("format track"));
return; return;
break; break;
@ -862,20 +817,10 @@ bx_floppy_ctrl_c::floppy_command(void)
// read input error checking). // read input error checking).
if (head != ((BX_FD_THIS s.command[1]>>2)&1)) { if (head != ((BX_FD_THIS s.command[1]>>2)&1)) {
BX_ERROR(("head number in command[1] doesn't match head field")); 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.status_reg0 = 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.status_reg1 = 0x04; // 0000 0100
BX_FD_THIS s.result[1] = 0x04; // 0000 0100 BX_FD_THIS s.status_reg2 = 0x00; // 0000 0000
BX_FD_THIS s.result[2] = 0x00; // 0000 0000 enter_result_phase();
BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive];
BX_FD_THIS s.result[4] = BX_FD_THIS s.head[drive];
BX_FD_THIS s.result[5] = BX_FD_THIS s.sector[drive];
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;
raise_interrupt();
return; return;
} }
@ -885,20 +830,10 @@ bx_floppy_ctrl_c::floppy_command(void)
BX_INFO(("attempt to read/write sector %u," BX_INFO(("attempt to read/write sector %u,"
" sectors/track=%u", (unsigned) sector, " sectors/track=%u", (unsigned) sector,
(unsigned) BX_FD_THIS s.media[drive].sectors_per_track)); (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.status_reg0 = 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.status_reg1 = 0x25; // 0010 0101
BX_FD_THIS s.result[1] = 0x25; // 0010 0101 BX_FD_THIS s.status_reg2 = 0x31; // 0011 0001
BX_FD_THIS s.result[2] = 0x31; // 0011 0001 enter_result_phase();
BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive];
BX_FD_THIS s.result[4] = BX_FD_THIS s.head[drive];
BX_FD_THIS s.result[5] = BX_FD_THIS s.sector[drive];
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;
raise_interrupt();
return; return;
} }
@ -906,9 +841,9 @@ bx_floppy_ctrl_c::floppy_command(void)
BX_PANIC(("sector_size not 512")); BX_PANIC(("sector_size not 512"));
} }
if ( cylinder >= BX_FD_THIS s.media[drive].tracks ) { if ( cylinder >= BX_FD_THIS s.media[drive].tracks ) {
BX_PANIC(("io: norm r/w parms out of range: sec#%02xh cyl#%02xh eot#%02xh head#%02xh", BX_PANIC(("io: norm r/w parms out of range: sec#%02xh cyl#%02xh eot#%02xh head#%02xh",
(unsigned) sector, (unsigned) cylinder, (unsigned) eot, (unsigned) sector, (unsigned) cylinder, (unsigned) eot,
(unsigned) head)); (unsigned) head));
return; return;
} }
@ -923,34 +858,20 @@ bx_floppy_ctrl_c::floppy_command(void)
BX_FD_THIS s.head[drive] = head; BX_FD_THIS s.head[drive] = head;
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.result_size = 7;
BX_FD_THIS s.result_index = 0;
// 0100 0HDD abnormal termination // 0100 0HDD abnormal termination
BX_FD_THIS s.status_reg0 = 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 // 1000 0101 end of cyl/NDAT/NID
BX_FD_THIS s.result[1] = 0x85; BX_FD_THIS s.status_reg1 = 0x85;
// 0000 0000 // 0000 0000
BX_FD_THIS s.result[2] = 0x00; BX_FD_THIS s.status_reg2 = 0x00;
BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive];
BX_FD_THIS s.result[4] = BX_FD_THIS s.head[drive];
BX_FD_THIS s.result[5] = BX_FD_THIS s.sector[drive];
BX_FD_THIS s.result[6] = 2; // sector size = 512
bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index, bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index,
bx_options.Ofloppy_command_delay->get (), 0 ); bx_options.Ofloppy_command_delay->get (), 0 );
/* data reg not ready, controller busy */ /* data reg not ready, controller busy */
BX_FD_THIS s.main_status_reg = 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; return;
} }
#if 0
if (eot != BX_FD_THIS s.media[drive].sectors_per_track)
BX_DEBUG(("io: bad eot #%02xh", (unsigned) eot));
#endif
if (cylinder != BX_FD_THIS s.cylinder[drive]) if (cylinder != BX_FD_THIS s.cylinder[drive])
BX_DEBUG(("io: cylinder request != current cylinder")); BX_DEBUG(("io: cylinder request != current cylinder"));
@ -969,23 +890,19 @@ bx_floppy_ctrl_c::floppy_command(void)
if ((BX_FD_THIS s.command[0] & 0x4f) == 0x46) { // read if ((BX_FD_THIS s.command[0] & 0x4f) == 0x46) { // read
floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer, floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer,
512, FROM_FLOPPY); 512, FROM_FLOPPY);
BX_FD_THIS s.floppy_buffer_index = 0;
DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1); DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1);
/* data reg not ready, controller busy */ /* data reg not ready, controller busy */
BX_FD_THIS s.main_status_reg = 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; return;
} }
else if ((BX_FD_THIS s.command[0] & 0x7f) == 0x45) { // write else if ((BX_FD_THIS s.command[0] & 0x7f) == 0x45) { // write
BX_FD_THIS s.floppy_buffer_index = 0;
DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1); DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1);
/* data reg not ready, controller busy */ /* data reg not ready, controller busy */
BX_FD_THIS s.main_status_reg = 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; return;
} }
else else
@ -994,12 +911,9 @@ bx_floppy_ctrl_c::floppy_command(void)
return; return;
break; break;
default: // invalid or unsupported command default: // invalid or unsupported command; these are captured in write() above
BX_FD_THIS s.result_size = 1; BX_PANIC(("You should never get here! cmd = 0x%02x",
BX_FD_THIS s.result_index = 0; BX_FD_THIS s.command[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;
} }
#endif #endif
} }
@ -1084,27 +998,7 @@ bx_floppy_ctrl_c::timer()
drive = BX_FD_THIS s.DOR & 0x03; drive = BX_FD_THIS s.DOR & 0x03;
switch ( BX_FD_THIS s.pending_command ) { switch ( BX_FD_THIS s.pending_command ) {
case 0x07: // recal case 0x07: // recal
BX_FD_THIS s.pending_command = 0;
/* write ready, not busy */
BX_FD_THIS s.cylinder[drive] = 0;
BX_FD_THIS s.main_status_reg = FD_MS_MRQ | (1 << drive);
BX_FD_THIS s.status_reg0 = 0x20 | (BX_FD_THIS s.head[drive]<<2) | drive;
if (BX_FD_THIS s.device_type[drive] == BX_FLOPPY_NONE) {
BX_FD_THIS s.status_reg0 |= 0x50;
}
else if (BX_FD_THIS s.media_present[drive] == 0) {
BX_FD_THIS s.status_reg0 |= 0x40;
BX_FD_THIS s.status_reg1 = 0x25;
BX_FD_THIS s.status_reg2 = 0x31;
}
raise_interrupt();
goto reset_changeline;
break;
case 0x0f: // seek case 0x0f: // seek
BX_FD_THIS s.pending_command = 0;
/* write ready, not busy */
BX_FD_THIS s.main_status_reg = FD_MS_MRQ | (1 << drive);
BX_FD_THIS s.status_reg0 = 0x20 | (BX_FD_THIS s.head[drive]<<2) | drive; BX_FD_THIS s.status_reg0 = 0x20 | (BX_FD_THIS s.head[drive]<<2) | drive;
if (BX_FD_THIS s.device_type[drive] == BX_FLOPPY_NONE) { if (BX_FD_THIS s.device_type[drive] == BX_FLOPPY_NONE) {
BX_FD_THIS s.status_reg0 |= 0x50; BX_FD_THIS s.status_reg0 |= 0x50;
@ -1114,29 +1008,18 @@ bx_floppy_ctrl_c::timer()
BX_FD_THIS s.status_reg1 = 0x25; BX_FD_THIS s.status_reg1 = 0x25;
BX_FD_THIS s.status_reg2 = 0x31; BX_FD_THIS s.status_reg2 = 0x31;
} }
/* reset changeline */
if (drive > 1) return;
if (BX_FD_THIS s.media_present[drive])
BX_FD_THIS s.DIR[drive] &= ~0x80; // clear disk change line
enter_idle_phase();
raise_interrupt(); raise_interrupt();
goto reset_changeline;
break; break;
case 0x4a: /* read ID */ case 0x4a: /* read ID */
BX_FD_THIS s.pending_command = 0; enter_result_phase();
/* read ready, busy */
BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO;
BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
raise_interrupt();
break;
case 0x46: // read normal data
case 0x66:
case 0xc6:
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 | FD_MS_BUSY | (1 << drive);
BX_FD_THIS s.status_reg0 = (BX_FD_THIS s.head[drive]<<2) | drive;
raise_interrupt();
break; break;
case 0xfe: // (contrived) RESET case 0xfe: // (contrived) RESET
@ -1155,11 +1038,6 @@ bx_floppy_ctrl_c::timer()
(unsigned) BX_FD_THIS s.pending_command)); (unsigned) BX_FD_THIS s.pending_command));
} }
return; return;
reset_changeline:
if (drive > 1) return;
if (BX_FD_THIS s.media_present[drive])
BX_FD_THIS s.DIR[drive] &= ~0x80; // clear disk change line
} }
void void
@ -1179,18 +1057,9 @@ bx_floppy_ctrl_c::dma_write(Bit8u *data_byte)
increment_sector(); // increment to next sector before retrieving next one increment_sector(); // increment to next sector before retrieving next one
BX_FD_THIS s.floppy_buffer_index = 0; BX_FD_THIS s.floppy_buffer_index = 0;
if (DEV_dma_get_tc()) { // Terminal Count line, done if (DEV_dma_get_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 | (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.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.status_reg1 = 0;
BX_FD_THIS s.result[1] = 0; BX_FD_THIS s.status_reg2 = 0;
BX_FD_THIS s.result[2] = 0;
BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive];
BX_FD_THIS s.result[4] = BX_FD_THIS s.head[drive];
BX_FD_THIS s.result[5] = BX_FD_THIS s.sector[drive];
BX_FD_THIS s.result[6] = 2;
if (bx_dbg.floppy) { if (bx_dbg.floppy) {
BX_INFO(("<<READ DONE>>")); BX_INFO(("<<READ DONE>>"));
@ -1201,8 +1070,8 @@ bx_floppy_ctrl_c::dma_write(Bit8u *data_byte)
BX_INFO((" sector = %u", (unsigned) BX_FD_THIS s.sector[drive])); BX_INFO((" sector = %u", (unsigned) BX_FD_THIS s.sector[drive]));
} }
raise_interrupt();
DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0); DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0);
enter_result_phase();
} }
else { // more data to transfer else { // more data to transfer
Bit32u logical_sector; Bit32u logical_sector;
@ -1258,17 +1127,9 @@ bx_floppy_ctrl_c::dma_read(Bit8u *data_byte)
} }
if ((BX_FD_THIS s.format_count == 0) || (DEV_dma_get_tc())) { if ((BX_FD_THIS s.format_count == 0) || (DEV_dma_get_tc())) {
BX_FD_THIS s.format_count = 0; 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.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
raise_interrupt();
DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0); DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0);
enter_result_phase();
} }
return; return;
} }
@ -1282,22 +1143,13 @@ bx_floppy_ctrl_c::dma_read(Bit8u *data_byte)
if ( BX_FD_THIS s.media[drive].write_protected ) { if ( BX_FD_THIS s.media[drive].write_protected ) {
// write protected error // write protected error
BX_INFO(("tried to write disk %u, which is write-protected", drive)); BX_INFO(("tried to write disk %u, which is write-protected", drive));
BX_FD_THIS s.result_size = 7;
BX_FD_THIS s.result_index = 0;
// ST0: IC1,0=01 (abnormal termination: started execution but failed) // ST0: IC1,0=01 (abnormal termination: started execution but failed)
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;
// ST1: DataError=1, NDAT=1, NotWritable=1, NID=1 // ST1: DataError=1, NDAT=1, NotWritable=1, NID=1
BX_FD_THIS s.result[1] = 0x27; // 0010 0111 BX_FD_THIS s.status_reg1 = 0x27; // 0010 0111
// ST2: CRCE=1, SERR=1, BCYL=1, NDAM=1. // ST2: CRCE=1, SERR=1, BCYL=1, NDAM=1.
BX_FD_THIS s.result[2] = 0x31; // 0011 0001 BX_FD_THIS s.status_reg2 = 0x31; // 0011 0001
BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive]; enter_result_phase();
BX_FD_THIS s.result[4] = BX_FD_THIS s.head[drive];
BX_FD_THIS s.result[5] = BX_FD_THIS s.sector[drive];
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 | (1 << drive);
raise_interrupt();
return; return;
} }
floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer, floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer,
@ -1305,18 +1157,10 @@ bx_floppy_ctrl_c::dma_read(Bit8u *data_byte)
increment_sector(); // increment to next sector after writing current one increment_sector(); // increment to next sector after writing current one
BX_FD_THIS s.floppy_buffer_index = 0; BX_FD_THIS s.floppy_buffer_index = 0;
if (DEV_dma_get_tc()) { // Terminal Count line, done if (DEV_dma_get_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.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.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.status_reg1 = 0;
BX_FD_THIS s.result[1] = 0; BX_FD_THIS s.status_reg2 = 0;
BX_FD_THIS s.result[2] = 0;
BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive];
BX_FD_THIS s.result[4] = BX_FD_THIS s.head[drive];
BX_FD_THIS s.result[5] = BX_FD_THIS s.sector[drive];
BX_FD_THIS s.result[6] = 2;
if (bx_dbg.floppy) { if (bx_dbg.floppy) {
BX_INFO(("<<WRITE DONE>>")); BX_INFO(("<<WRITE DONE>>"));
BX_INFO(("AFTER")); BX_INFO(("AFTER"));
@ -1326,8 +1170,8 @@ bx_floppy_ctrl_c::dma_read(Bit8u *data_byte)
BX_INFO((" sector = %u", (unsigned) BX_FD_THIS s.sector[drive])); BX_INFO((" sector = %u", (unsigned) BX_FD_THIS s.sector[drive]));
} }
raise_interrupt();
DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0); DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0);
enter_result_phase();
} }
else { // more data to transfer else { // more data to transfer
} // else } // else
@ -1475,11 +1319,11 @@ bx_floppy_ctrl_c::evaluate_media(unsigned type, char *path, floppy_t *media)
#endif #endif
#ifdef WIN32 #ifdef WIN32
if ( (path[1] == ':') && (strlen(path) == 2) ) { if ( (path[1] == ':') && (strlen(path) == 2) ) {
wsprintf(sTemp, "\\\\.\\%s", path); wsprintf(sTemp, "\\\\.\\%s", path);
media->fd = open(sTemp, BX_RDWR); media->fd = open(sTemp, BX_RDWR);
} else { } else {
media->fd = open(path, BX_RDWR); media->fd = open(path, BX_RDWR);
} }
#else #else
media->fd = open(path, BX_RDWR); media->fd = open(path, BX_RDWR);
#endif #endif
@ -1494,11 +1338,11 @@ bx_floppy_ctrl_c::evaluate_media(unsigned type, char *path, floppy_t *media)
#endif #endif
#ifdef WIN32 #ifdef WIN32
if ( (path[1] == ':') && (strlen(path) == 2) ) { if ( (path[1] == ':') && (strlen(path) == 2) ) {
wsprintf(sTemp, "\\\\.\\%s", path); wsprintf(sTemp, "\\\\.\\%s", path);
media->fd = open(sTemp, BX_RDONLY); media->fd = open(sTemp, BX_RDONLY);
} else { } else {
media->fd = open(path, BX_RDONLY); media->fd = open(path, BX_RDONLY);
} }
#else #else
media->fd = open(path, BX_RDONLY); media->fd = open(path, BX_RDONLY);
#endif #endif
@ -1566,11 +1410,11 @@ bx_floppy_ctrl_c::evaluate_media(unsigned type, char *path, floppy_t *media)
media->tracks = 80; media->tracks = 80;
media->heads = 2; media->heads = 2;
} }
else if (stat_buf.st_size == 1763328) { else if (stat_buf.st_size == 1763328) {
media->sectors_per_track = 21; media->sectors_per_track = 21;
media->tracks = 82; media->tracks = 82;
media->heads = 2; media->heads = 2;
} }
else { else {
BX_INFO(("evaluate_media: file '%s' of unknown size %lu", BX_INFO(("evaluate_media: file '%s' of unknown size %lu",
path, (unsigned long) stat_buf.st_size)); path, (unsigned long) stat_buf.st_size));
@ -1643,3 +1487,68 @@ bx_floppy_ctrl_c::evaluate_media(unsigned type, char *path, floppy_t *media)
} }
} }
void
bx_floppy_ctrl_c::enter_result_phase(void)
{
Bit8u drive;
drive = BX_FD_THIS s.DOR & 0x03;
/* these are always the same */
BX_FD_THIS s.result_index = 0;
BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
/* invalid command */
if ((BX_FD_THIS s.status_reg0 & 0xc0) == 0x80) {
BX_FD_THIS s.result_size = 1;
BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
return;
}
switch (BX_FD_THIS s.pending_command) {
case 0x04: // get status
BX_FD_THIS s.result_size = 1;
BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg3;
break;
case 0x08: // sense interrupt
BX_FD_THIS s.result_size = 2;
BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
BX_FD_THIS s.result[1] = BX_FD_THIS s.cylinder[drive];
break;
case 0x4a: // read ID
case 0x4d: // format track
case 0x46: // read normal data
case 0x66:
case 0xc6:
case 0xe6:
case 0x45: // write normal data
case 0xc5:
BX_FD_THIS s.result_size = 7;
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;
BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive];
BX_FD_THIS s.result[4] = BX_FD_THIS s.head[drive];
BX_FD_THIS s.result[5] = BX_FD_THIS s.sector[drive];
BX_FD_THIS s.result[6] = 2; /* sector size code */
raise_interrupt();
break;
}
}
void
bx_floppy_ctrl_c::enter_idle_phase(void)
{
BX_FD_THIS s.main_status_reg &= 0x0f; // leave drive status untouched
BX_FD_THIS s.main_status_reg |= FD_MS_MRQ; // data register ready
BX_FD_THIS s.command_complete = 1; /* waiting for new command */
BX_FD_THIS s.command_index = 0;
BX_FD_THIS s.command_size = 0;
BX_FD_THIS s.pending_command = 0;
BX_FD_THIS s.floppy_buffer_index = 0;
}

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: floppy.h,v 1.15 2002-11-10 10:14:55 vruppert Exp $ // $Id: floppy.h,v 1.16 2002-11-30 09:39:29 vruppert Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2002 MandrakeSoft S.A. // Copyright (C) 2002 MandrakeSoft S.A.
@ -127,6 +127,8 @@ private:
BX_FD_SMF void floppy_command(void); BX_FD_SMF void floppy_command(void);
BX_FD_SMF void floppy_xfer(Bit8u drive, Bit32u offset, Bit8u *buffer, Bit32u bytes, Bit8u direction); BX_FD_SMF void floppy_xfer(Bit8u drive, Bit32u offset, Bit8u *buffer, Bit32u bytes, Bit8u direction);
BX_FD_SMF void raise_interrupt(void); BX_FD_SMF void raise_interrupt(void);
BX_FD_SMF void enter_idle_phase(void);
BX_FD_SMF void enter_result_phase(void);
static void timer_handler(void *); static void timer_handler(void *);
public: public: