- 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.
@ -101,7 +101,7 @@ bx_floppy_ctrl_c::init(void)
{
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_register_irq(6, "Floppy Drive");
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_present[0] = 1;
else
bx_options.floppya.Ostatus->set(BX_EJECTED);
bx_options.floppya.Ostatus->set(BX_EJECTED);
#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(),
MED.write_protected, MED.heads, MED.tracks, MED.sectors_per_track));
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));
#undef MED
}
}
@ -212,10 +212,10 @@ bx_floppy_ctrl_c::init(void)
& BX_FD_THIS s.media[1]))
BX_FD_THIS s.media_present[1] = 1;
else
bx_options.floppyb.Ostatus->set(BX_EJECTED);
bx_options.floppyb.Ostatus->set(BX_EJECTED);
#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(),
MED.write_protected, MED.heads, MED.tracks, MED.sectors_per_track));
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));
#undef MED
}
}
@ -233,7 +233,7 @@ bx_floppy_ctrl_c::init(void)
if (BX_FD_THIS s.floppy_timer_index == BX_NULL_TIMER_HANDLE) {
BX_FD_THIS s.floppy_timer_index =
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",
@ -247,19 +247,10 @@ bx_floppy_ctrl_c::reset(unsigned type)
{
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.reset_sensei = 0; /* no reset result present */
BX_FD_THIS s.result_index = 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.main_status_reg = 0;
BX_FD_THIS s.status_reg0 = 0;
BX_FD_THIS s.status_reg1 = 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.floppy_buffer_index = 0;
DEV_pic_lower_irq(6);
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++];
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;
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);
break;
@ -360,12 +347,12 @@ bx_floppy_ctrl_c::read(Bit32u address, unsigned io_len)
switch( BX_FD_THIS s.DOR & 0x03 )
{
case 0x00:
if( (BX_FD_THIS s.DOR & 0x10) == 0) break;
return(2);
case 0x01:
if( (BX_FD_THIS s.DOR & 0x20) == 0) break;
return(1);
case 0x00:
if( (BX_FD_THIS s.DOR & 0x10) == 0) break;
return(2);
case 0x01:
if( (BX_FD_THIS s.DOR & 0x20) == 0) break;
return(1);
}
return(3);
@ -524,15 +511,17 @@ bx_floppy_ctrl_c::write(Bit32u address, Bit32u value, unsigned io_len)
// 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.command_size = 0; // make sure we don't try to process this command
BX_FD_THIS s.status_reg0 = 0x80; // status: invalid command
enter_result_phase();
break;
default:
BX_ERROR(("io_write: 0x3f5: invalid floppy command 0x%02x",
(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
enter_result_phase();
break;
}
}
@ -605,7 +594,8 @@ bx_floppy_ctrl_c::floppy_command(void)
BX_FD_THIS s.main_status_reg |= 20;
#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
// execution: specified parameters are loaded
// 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;
if (BX_FD_THIS s.command[2] & 0x01)
BX_ERROR(("non DMA mode selected"));
BX_FD_THIS s.main_status_reg = FD_MS_MRQ;
enter_idle_phase();
return;
break;
case 0x04: // get status
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.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);
if (BX_FD_THIS s.cylinder[drive] == 0) BX_FD_THIS s.result[0] |= 0x10;
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;
if (BX_FD_THIS s.cylinder[drive] == 0) BX_FD_THIS s.status_reg3 |= 0x10;
enter_result_phase();
return;
break;
@ -651,10 +639,10 @@ bx_floppy_ctrl_c::floppy_command(void)
* controller set to non-busy
* error condition noted in Status reg 0's equipment check bit
* 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.pending_command = 0x07; // recalibrate pending
return;
break;
@ -669,7 +657,6 @@ bx_floppy_ctrl_c::floppy_command(void)
drive = BX_FD_THIS s.DOR & 0x03;
if (!BX_FD_THIS s.pending_irq) {
BX_FD_THIS s.status_reg0 = 0x80;
BX_FD_THIS s.result_size = 1;
}
else {
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 |= (BX_FD_THIS s.head[drive] << 2) | drive;
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"));
enter_result_phase();
return;
break;
@ -712,7 +693,6 @@ bx_floppy_ctrl_c::floppy_command(void)
bx_options.Ofloppy_command_delay->get (), 0 );
/* data reg not ready, drive busy */
BX_FD_THIS s.main_status_reg = (1 << drive);
BX_FD_THIS s.pending_command = 0x0f; /* seek pending */
return;
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 (fifothr = 0x%02x)", BX_FD_THIS s.command[2] & 0x0f ));
BX_DEBUG(("configure (pretrk = 0x%02x)", BX_FD_THIS s.command[3] ));
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_BUSY;
enter_idle_phase();
return;
break;
@ -743,20 +720,11 @@ bx_floppy_ctrl_c::floppy_command(void)
}
if (BX_FD_THIS s.device_type[drive] == BX_FLOPPY_NONE)
BX_PANIC(("floppy_command(): read ID: bad drive #%d", drive));
BX_FD_THIS s.result_size = 7;
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_FD_THIS s.status_reg0 = (BX_FD_THIS s.head[drive]<<2) | drive;
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_BUSY;
BX_FD_THIS s.pending_command = 0x4a; /* read ID pending */
return;
break;
@ -784,31 +752,19 @@ bx_floppy_ctrl_c::floppy_command(void)
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;
raise_interrupt();
BX_FD_THIS s.status_reg1 = 0x25; // 0010 0101
BX_FD_THIS s.status_reg2 = 0x31; // 0011 0001
enter_result_phase();
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;
raise_interrupt();
BX_FD_THIS s.status_reg1 = 0x27; // 0010 0111
BX_FD_THIS s.status_reg2 = 0x31; // 0011 0001
enter_result_phase();
return;
}
@ -819,7 +775,6 @@ bx_floppy_ctrl_c::floppy_command(void)
/* 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;
@ -862,20 +817,10 @@ bx_floppy_ctrl_c::floppy_command(void)
// 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"));
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] = 0x04; // 0000 0100
BX_FD_THIS s.result[2] = 0x00; // 0000 0000
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();
BX_FD_THIS s.status_reg1 = 0x04; // 0000 0100
BX_FD_THIS s.status_reg2 = 0x00; // 0000 0000
enter_result_phase();
return;
}
@ -885,20 +830,10 @@ bx_floppy_ctrl_c::floppy_command(void)
BX_INFO(("attempt to read/write sector %u,"
" sectors/track=%u", (unsigned) sector,
(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.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];
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();
BX_FD_THIS s.status_reg1 = 0x25; // 0010 0101
BX_FD_THIS s.status_reg2 = 0x31; // 0011 0001
enter_result_phase();
return;
}
@ -906,9 +841,9 @@ bx_floppy_ctrl_c::floppy_command(void)
BX_PANIC(("sector_size not 512"));
}
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",
(unsigned) sector, (unsigned) cylinder, (unsigned) eot,
(unsigned) head));
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) head));
return;
}
@ -923,34 +858,20 @@ bx_floppy_ctrl_c::floppy_command(void)
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.result_size = 7;
BX_FD_THIS s.result_index = 0;
// 0100 0HDD abnormal termination
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] = 0x85;
BX_FD_THIS s.status_reg1 = 0x85;
// 0000 0000
BX_FD_THIS s.result[2] = 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_FD_THIS s.status_reg2 = 0x00;
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_BUSY;
BX_FD_THIS s.pending_command = BX_FD_THIS s.command[0];
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])
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
floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer,
512, FROM_FLOPPY);
BX_FD_THIS s.floppy_buffer_index = 0;
DEV_dma_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 = BX_FD_THIS s.command[0];
return;
}
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);
/* data reg not ready, controller busy */
BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
BX_FD_THIS s.pending_command = BX_FD_THIS s.command[0];
return;
}
else
@ -994,12 +911,9 @@ bx_floppy_ctrl_c::floppy_command(void)
return;
break;
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;
default: // invalid or unsupported command; these are captured in write() above
BX_PANIC(("You should never get here! cmd = 0x%02x",
BX_FD_THIS s.command[0]));
}
#endif
}
@ -1084,27 +998,7 @@ bx_floppy_ctrl_c::timer()
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.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
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;
if (BX_FD_THIS s.device_type[drive] == BX_FLOPPY_NONE) {
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_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();
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.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();
enter_result_phase();
break;
case 0xfe: // (contrived) RESET
@ -1155,11 +1038,6 @@ bx_floppy_ctrl_c::timer()
(unsigned) BX_FD_THIS s.pending_command));
}
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
@ -1179,18 +1057,9 @@ bx_floppy_ctrl_c::dma_write(Bit8u *data_byte)
increment_sector(); // increment to next sector before retrieving next one
BX_FD_THIS s.floppy_buffer_index = 0;
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.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];
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;
BX_FD_THIS s.status_reg1 = 0;
BX_FD_THIS s.status_reg2 = 0;
if (bx_dbg.floppy) {
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]));
}
raise_interrupt();
DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0);
enter_result_phase();
}
else { // more data to transfer
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())) {
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
raise_interrupt();
DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0);
enter_result_phase();
}
return;
}
@ -1282,22 +1143,13 @@ bx_floppy_ctrl_c::dma_read(Bit8u *data_byte)
if ( BX_FD_THIS s.media[drive].write_protected ) {
// write protected error
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)
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
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.
BX_FD_THIS s.result[2] = 0x31; // 0011 0001
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 | (1 << drive);
raise_interrupt();
BX_FD_THIS s.status_reg2 = 0x31; // 0011 0001
enter_result_phase();
return;
}
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
BX_FD_THIS s.floppy_buffer_index = 0;
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.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];
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;
BX_FD_THIS s.status_reg1 = 0;
BX_FD_THIS s.status_reg2 = 0;
if (bx_dbg.floppy) {
BX_INFO(("<<WRITE DONE>>"));
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]));
}
raise_interrupt();
DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0);
enter_result_phase();
}
else { // more data to transfer
} // else
@ -1475,11 +1319,11 @@ bx_floppy_ctrl_c::evaluate_media(unsigned type, char *path, floppy_t *media)
#endif
#ifdef WIN32
if ( (path[1] == ':') && (strlen(path) == 2) ) {
wsprintf(sTemp, "\\\\.\\%s", path);
media->fd = open(sTemp, BX_RDWR);
} else {
media->fd = open(path, BX_RDWR);
}
wsprintf(sTemp, "\\\\.\\%s", path);
media->fd = open(sTemp, BX_RDWR);
} else {
media->fd = open(path, BX_RDWR);
}
#else
media->fd = open(path, BX_RDWR);
#endif
@ -1494,11 +1338,11 @@ bx_floppy_ctrl_c::evaluate_media(unsigned type, char *path, floppy_t *media)
#endif
#ifdef WIN32
if ( (path[1] == ':') && (strlen(path) == 2) ) {
wsprintf(sTemp, "\\\\.\\%s", path);
media->fd = open(sTemp, BX_RDONLY);
} else {
media->fd = open(path, BX_RDONLY);
}
wsprintf(sTemp, "\\\\.\\%s", path);
media->fd = open(sTemp, BX_RDONLY);
} else {
media->fd = open(path, BX_RDONLY);
}
#else
media->fd = open(path, BX_RDONLY);
#endif
@ -1566,11 +1410,11 @@ bx_floppy_ctrl_c::evaluate_media(unsigned type, char *path, floppy_t *media)
media->tracks = 80;
media->heads = 2;
}
else if (stat_buf.st_size == 1763328) {
else if (stat_buf.st_size == 1763328) {
media->sectors_per_track = 21;
media->tracks = 82;
media->heads = 2;
}
}
else {
BX_INFO(("evaluate_media: file '%s' of unknown size %lu",
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.
@ -127,6 +127,8 @@ private:
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 raise_interrupt(void);
BX_FD_SMF void enter_idle_phase(void);
BX_FD_SMF void enter_result_phase(void);
static void timer_handler(void *);
public: