- more accurate timing for reading data using a motor speed of 300 RPM. This is
important at boot time if the user wants to control the boot process. TODO: * implement timing for write and format commands * more accurate timing for seek, recalibrate and maybe others * raw floppy access slows down the emulation, use separate threads (???) - irq line goes low with when reading the first result byte - the drive status bits are only modified after reading the first result byte - handling of floppy command 'sense interrupt status' simplified - improved debug messages for i/o port reads and writes
This commit is contained in:
parent
086ee4c9aa
commit
b88facfb66
@ -1,5 +1,5 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// $Id: floppy.cc,v 1.79 2005-08-24 20:44:55 vruppert Exp $
|
// $Id: floppy.cc,v 1.80 2005-08-31 19:48:03 vruppert Exp $
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Copyright (C) 2002 MandrakeSoft S.A.
|
// Copyright (C) 2002 MandrakeSoft S.A.
|
||||||
@ -132,7 +132,7 @@ bx_floppy_ctrl_c::init(void)
|
|||||||
{
|
{
|
||||||
Bit8u i;
|
Bit8u i;
|
||||||
|
|
||||||
BX_DEBUG(("Init $Id: floppy.cc,v 1.79 2005-08-24 20:44:55 vruppert Exp $"));
|
BX_DEBUG(("Init $Id: floppy.cc,v 1.80 2005-08-31 19:48:03 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++) {
|
||||||
@ -374,38 +374,31 @@ bx_floppy_ctrl_c::read(Bit32u address, unsigned io_len)
|
|||||||
#else
|
#else
|
||||||
UNUSED(this_ptr);
|
UNUSED(this_ptr);
|
||||||
#endif // !BX_USE_FD_SMF
|
#endif // !BX_USE_FD_SMF
|
||||||
Bit8u value, drive;
|
Bit8u value = 0, drive;
|
||||||
|
|
||||||
if (bx_dbg.floppy)
|
|
||||||
BX_INFO(("read access to port %04x", (unsigned) address));
|
|
||||||
|
|
||||||
switch (address) {
|
switch (address) {
|
||||||
#if BX_DMA_FLOPPY_IO
|
#if BX_DMA_FLOPPY_IO
|
||||||
case 0x3F2: // diskette controller digital output register
|
case 0x3F2: // diskette controller digital output register
|
||||||
value = BX_FD_THIS s.DOR;
|
value = BX_FD_THIS s.DOR;
|
||||||
return(value);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x3F4: /* diskette controller main status register */
|
case 0x3F4: /* diskette controller main status register */
|
||||||
value = BX_FD_THIS s.main_status_reg;
|
value = BX_FD_THIS s.main_status_reg;
|
||||||
return(value);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x3F5: /* diskette controller data */
|
case 0x3F5: /* diskette controller data */
|
||||||
if (BX_FD_THIS s.result_size == 0) {
|
if (BX_FD_THIS s.result_size == 0) {
|
||||||
BX_ERROR(("port 0x3f5: no results to read"));
|
BX_ERROR(("port 0x3f5: no results to read"));
|
||||||
BX_FD_THIS s.main_status_reg = 0;
|
BX_FD_THIS s.main_status_reg = 0;
|
||||||
return BX_FD_THIS s.result[0];
|
value = BX_FD_THIS s.result[0];
|
||||||
|
} else {
|
||||||
|
value = BX_FD_THIS s.result[BX_FD_THIS s.result_index++];
|
||||||
|
BX_FD_THIS s.main_status_reg &= 0xF0;
|
||||||
|
BX_FD_THIS lower_interrupt();
|
||||||
|
if (BX_FD_THIS s.result_index >= BX_FD_THIS s.result_size) {
|
||||||
|
enter_idle_phase();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
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) {
|
|
||||||
if (!BX_FD_THIS s.reset_sensei) BX_FD_THIS s.pending_irq = 0;
|
|
||||||
DEV_pic_lower_irq(6);
|
|
||||||
enter_idle_phase();
|
|
||||||
}
|
|
||||||
return(value);
|
|
||||||
break;
|
break;
|
||||||
#endif // #if BX_DMA_FLOPPY_IO
|
#endif // #if BX_DMA_FLOPPY_IO
|
||||||
|
|
||||||
@ -432,17 +425,15 @@ bx_floppy_ctrl_c::read(Bit32u address, unsigned io_len)
|
|||||||
default: // BX_FLOPPY_NONE
|
default: // BX_FLOPPY_NONE
|
||||||
value = 0x20;
|
value = 0x20;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
} else {
|
||||||
value = 0x20;
|
value = 0x20;
|
||||||
}
|
}
|
||||||
return( value );
|
break;
|
||||||
|
|
||||||
case 0x3F6: // Reserved for future floppy controllers
|
case 0x3F6: // Reserved for future floppy controllers
|
||||||
// This address shared with the hard drive controller
|
// This address shared with the hard drive controller
|
||||||
value = DEV_hd_read_handler(bx_devices.pluginHardDrive, address, io_len);
|
value = DEV_hd_read_handler(bx_devices.pluginHardDrive, address, io_len);
|
||||||
return( value );
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x3F7: // diskette controller digital input register
|
case 0x3F7: // diskette controller digital input register
|
||||||
@ -453,13 +444,15 @@ bx_floppy_ctrl_c::read(Bit32u address, unsigned io_len)
|
|||||||
value &= 0x7f;
|
value &= 0x7f;
|
||||||
// add in diskette change line
|
// add in diskette change line
|
||||||
value |= (BX_FD_THIS s.DIR[BX_FD_THIS s.DOR & 0x03] & 0x80);
|
value |= (BX_FD_THIS s.DIR[BX_FD_THIS s.DOR & 0x03] & 0x80);
|
||||||
return( value );
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
BX_ERROR(("io_read: unsupported address 0x%04x", (unsigned) address));
|
BX_ERROR(("io_read: unsupported address 0x%04x", (unsigned) address));
|
||||||
return(0);
|
return(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
BX_DEBUG(("read access to port %04x returns 0x%02x", address, value));
|
||||||
|
return (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -487,9 +480,7 @@ bx_floppy_ctrl_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
|||||||
Bit8u drive_select;
|
Bit8u drive_select;
|
||||||
Bit8u motor_on_drive0, motor_on_drive1;
|
Bit8u motor_on_drive0, motor_on_drive1;
|
||||||
|
|
||||||
if (bx_dbg.floppy)
|
BX_DEBUG(("write access to port %04x, value=%02x", address, value));
|
||||||
BX_INFO(("write access to port %04x, value=%02x",
|
|
||||||
(unsigned) address, (unsigned) value));
|
|
||||||
|
|
||||||
switch (address) {
|
switch (address) {
|
||||||
#if BX_DMA_FLOPPY_IO
|
#if BX_DMA_FLOPPY_IO
|
||||||
@ -553,7 +544,8 @@ bx_floppy_ctrl_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
|||||||
BX_FD_THIS s.command_complete = 0;
|
BX_FD_THIS s.command_complete = 0;
|
||||||
BX_FD_THIS s.command_index = 1;
|
BX_FD_THIS s.command_index = 1;
|
||||||
/* read/write command in progress */
|
/* read/write command in progress */
|
||||||
BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_BUSY;
|
BX_FD_THIS s.main_status_reg &= 0x0f; // leave drive status untouched
|
||||||
|
BX_FD_THIS s.main_status_reg |= FD_MS_MRQ | FD_MS_BUSY;
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case 0x03: /* specify */
|
case 0x03: /* specify */
|
||||||
BX_FD_THIS s.command_size = 3;
|
BX_FD_THIS s.command_size = 3;
|
||||||
@ -670,7 +662,7 @@ bx_floppy_ctrl_c::floppy_command(void)
|
|||||||
Bit8u motor_on;
|
Bit8u motor_on;
|
||||||
Bit8u head, drive, cylinder, sector, eot;
|
Bit8u head, drive, cylinder, sector, eot;
|
||||||
Bit8u sector_size, data_length;
|
Bit8u sector_size, data_length;
|
||||||
Bit32u logical_sector;
|
Bit32u logical_sector, sector_time;
|
||||||
|
|
||||||
// Print command
|
// Print command
|
||||||
char buf[9+(9*5)+1], *p = buf;
|
char buf[9+(9*5)+1], *p = buf;
|
||||||
@ -746,19 +738,14 @@ bx_floppy_ctrl_c::floppy_command(void)
|
|||||||
* byte0 = status reg0
|
* byte0 = status reg0
|
||||||
* byte1 = current cylinder number (0 to 79)
|
* byte1 = current cylinder number (0 to 79)
|
||||||
*/
|
*/
|
||||||
drive = BX_FD_THIS s.DOR & 0x03;
|
if (BX_FD_THIS s.reset_sensei > 0) {
|
||||||
if (!BX_FD_THIS s.pending_irq) {
|
drive = 4 - BX_FD_THIS s.reset_sensei;
|
||||||
|
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--;
|
||||||
|
} else if (!BX_FD_THIS s.pending_irq) {
|
||||||
BX_FD_THIS s.status_reg0 = 0x80;
|
BX_FD_THIS s.status_reg0 = 0x80;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (BX_FD_THIS s.reset_sensei > 0) {
|
|
||||||
drive = 4 - BX_FD_THIS s.reset_sensei;
|
|
||||||
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_DEBUG(("sense interrupt status"));
|
BX_DEBUG(("sense interrupt status"));
|
||||||
enter_result_phase();
|
enter_result_phase();
|
||||||
return;
|
return;
|
||||||
@ -971,31 +958,26 @@ 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);
|
||||||
|
|
||||||
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;
|
||||||
return;
|
// time to read one sector at 300 rpm
|
||||||
}
|
sector_time = 200000 / BX_FD_THIS s.media[drive].sectors_per_track;
|
||||||
else if ((BX_FD_THIS s.command[0] & 0x7f) == 0x45) { // write
|
bx_pc_system.activate_timer(BX_FD_THIS s.floppy_timer_index,
|
||||||
|
sector_time , 0);
|
||||||
DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1);
|
} else if ((BX_FD_THIS s.command[0] & 0x7f) == 0x45) { // write
|
||||||
|
|
||||||
/* 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;
|
||||||
return;
|
DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
BX_PANIC(("floppy_command(): unknown read/write command"));
|
BX_PANIC(("floppy_command(): unknown read/write command"));
|
||||||
|
return;
|
||||||
return;
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: // invalid or unsupported command; these are captured in write() above
|
default: // invalid or unsupported command; these are captured in write() above
|
||||||
BX_PANIC(("You should never get here! cmd = 0x%02x",
|
BX_PANIC(("You should never get here! cmd = 0x%02x",
|
||||||
BX_FD_THIS s.command[0]));
|
BX_FD_THIS s.command[0]));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1143,6 +1125,14 @@ bx_floppy_ctrl_c::timer()
|
|||||||
enter_result_phase();
|
enter_result_phase();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0x46: // read normal data
|
||||||
|
case 0x66:
|
||||||
|
case 0xc6:
|
||||||
|
case 0xe6:
|
||||||
|
// transfer next sector
|
||||||
|
DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
case 0xfe: // (contrived) RESET
|
case 0xfe: // (contrived) RESET
|
||||||
theFloppyController->reset(BX_RESET_SOFTWARE);
|
theFloppyController->reset(BX_RESET_SOFTWARE);
|
||||||
BX_FD_THIS s.pending_command = 0;
|
BX_FD_THIS s.pending_command = 0;
|
||||||
@ -1189,13 +1179,12 @@ bx_floppy_ctrl_c::dma_write(Bit8u *data_byte)
|
|||||||
BX_INFO((" head = %u", (unsigned) BX_FD_THIS s.head[drive]));
|
BX_INFO((" head = %u", (unsigned) BX_FD_THIS s.head[drive]));
|
||||||
BX_INFO((" cylinder = %u", (unsigned) BX_FD_THIS s.cylinder[drive]));
|
BX_INFO((" cylinder = %u", (unsigned) BX_FD_THIS s.cylinder[drive]));
|
||||||
BX_INFO((" sector = %u", (unsigned) BX_FD_THIS s.sector[drive]));
|
BX_INFO((" sector = %u", (unsigned) BX_FD_THIS s.sector[drive]));
|
||||||
}
|
}
|
||||||
|
|
||||||
DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0);
|
DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0);
|
||||||
enter_result_phase();
|
enter_result_phase();
|
||||||
}
|
} else { // more data to transfer
|
||||||
else { // more data to transfer
|
Bit32u logical_sector, sector_time;
|
||||||
Bit32u logical_sector;
|
|
||||||
|
|
||||||
// original assumed all floppies had two sides...now it does not *delete this comment line*
|
// original assumed all floppies had two sides...now it does not *delete this comment line*
|
||||||
logical_sector = (BX_FD_THIS s.cylinder[drive] * BX_FD_THIS s.media[drive].heads *
|
logical_sector = (BX_FD_THIS s.cylinder[drive] * BX_FD_THIS s.media[drive].heads *
|
||||||
@ -1206,8 +1195,13 @@ bx_floppy_ctrl_c::dma_write(Bit8u *data_byte)
|
|||||||
|
|
||||||
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);
|
||||||
}
|
DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0);
|
||||||
|
// time to read one sector at 300 rpm
|
||||||
|
sector_time = 200000 / BX_FD_THIS s.media[drive].sectors_per_track;
|
||||||
|
bx_pc_system.activate_timer(BX_FD_THIS s.floppy_timer_index,
|
||||||
|
sector_time , 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1315,8 +1309,10 @@ bx_floppy_ctrl_c::raise_interrupt(void)
|
|||||||
void
|
void
|
||||||
bx_floppy_ctrl_c::lower_interrupt(void)
|
bx_floppy_ctrl_c::lower_interrupt(void)
|
||||||
{
|
{
|
||||||
DEV_pic_lower_irq(6);
|
if (BX_FD_THIS s.pending_irq) {
|
||||||
BX_FD_THIS s.pending_irq = 0;
|
DEV_pic_lower_irq(6);
|
||||||
|
BX_FD_THIS s.pending_irq = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1693,7 +1689,8 @@ bx_floppy_ctrl_c::enter_result_phase(void)
|
|||||||
|
|
||||||
/* these are always the same */
|
/* these are always the same */
|
||||||
BX_FD_THIS s.result_index = 0;
|
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.main_status_reg &= 0x0f; // leave drive status untouched
|
||||||
|
BX_FD_THIS s.main_status_reg |= FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
|
||||||
|
|
||||||
/* invalid command */
|
/* invalid command */
|
||||||
if ((BX_FD_THIS s.status_reg0 & 0xc0) == 0x80) {
|
if ((BX_FD_THIS s.status_reg0 & 0xc0) == 0x80) {
|
||||||
|
Loading…
Reference in New Issue
Block a user