SM(S)C FDC37C669 Super I/O chip rewrite and proper FDC power down behavior, fixes floppy drive errors on the new Daeweoo machine.
This commit is contained in:
149
src/floppy/fdc.c
149
src/floppy/fdc.c
@@ -212,6 +212,7 @@ fdc_ctrl_reset(void *priv)
|
||||
fdc->lock = 0;
|
||||
fdc->head = 0;
|
||||
fdc->step = 0;
|
||||
fdc->power_down = 0;
|
||||
if (!(fdc->flags & FDC_FLAG_AT))
|
||||
fdc->rate = 2;
|
||||
}
|
||||
@@ -257,7 +258,7 @@ fdc_set_wrong_am(fdc_t *fdc)
|
||||
int
|
||||
fdc_get_drive(fdc_t *fdc)
|
||||
{
|
||||
return fdc->drive;
|
||||
return (int) fdc->drive;
|
||||
}
|
||||
|
||||
int fdc_get_bitcell_period(fdc_t *fdc);
|
||||
@@ -270,7 +271,7 @@ fdc_get_perp(fdc_t *fdc)
|
||||
if (!(fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_PCJR))
|
||||
return 0;
|
||||
|
||||
return fdc->perp;
|
||||
return (int) fdc->perp;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -292,7 +293,7 @@ fdc_get_gap2(fdc_t *fdc, int drive)
|
||||
int
|
||||
fdc_get_format_n(fdc_t *fdc)
|
||||
{
|
||||
return fdc->format_n;
|
||||
return (int) fdc->format_n;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -321,7 +322,7 @@ fdc_stop_id_request(fdc_t *fdc)
|
||||
int
|
||||
fdc_get_gap(fdc_t *fdc)
|
||||
{
|
||||
return fdc->gap;
|
||||
return (int) fdc->gap;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -333,7 +334,7 @@ fdc_get_dtl(fdc_t *fdc)
|
||||
int
|
||||
fdc_get_format_sectors(fdc_t *fdc)
|
||||
{
|
||||
return fdc->format_sectors;
|
||||
return (int) fdc->format_sectors;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -418,6 +419,12 @@ fdc_update_rates(fdc_t *fdc)
|
||||
fdc_rate(fdc, 3);
|
||||
}
|
||||
|
||||
void
|
||||
fdc_set_power_down(fdc_t *fdc, uint8_t power_down)
|
||||
{
|
||||
fdc->power_down = power_down;
|
||||
}
|
||||
|
||||
void
|
||||
fdc_update_max_track(fdc_t *fdc, int max_track)
|
||||
{
|
||||
@@ -427,7 +434,7 @@ fdc_update_max_track(fdc_t *fdc, int max_track)
|
||||
void
|
||||
fdc_update_enh_mode(fdc_t *fdc, int enh_mode)
|
||||
{
|
||||
fdc->enh_mode = enh_mode;
|
||||
fdc->enh_mode = !!enh_mode;
|
||||
fdc_update_rates(fdc);
|
||||
}
|
||||
|
||||
@@ -490,7 +497,7 @@ fdc_update_drvrate(fdc_t *fdc, int drive, int drvrate)
|
||||
void
|
||||
fdc_update_drv2en(fdc_t *fdc, int drv2en)
|
||||
{
|
||||
fdc->drv2en = drv2en;
|
||||
fdc->drv2en = !!drv2en;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -500,37 +507,34 @@ fdc_update_rate(fdc_t *fdc, int drive)
|
||||
fdc->bit_rate = 500;
|
||||
else if ((fdc->rwc[drive] == 3) && fdc->enh_mode)
|
||||
fdc->bit_rate = 250;
|
||||
else
|
||||
switch (fdc->rate) {
|
||||
case 0: /*High density*/
|
||||
fdc->bit_rate = 500;
|
||||
break;
|
||||
case 1: /*Double density (360 rpm)*/
|
||||
switch (fdc->drvrate[drive]) {
|
||||
case 0:
|
||||
fdc->bit_rate = 300;
|
||||
break;
|
||||
case 1:
|
||||
fdc->bit_rate = 500;
|
||||
break;
|
||||
case 2:
|
||||
fdc->bit_rate = 2000;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2: /*Double density*/
|
||||
fdc->bit_rate = 250;
|
||||
break;
|
||||
case 3: /*Extended density*/
|
||||
fdc->bit_rate = 1000;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
else switch (fdc->rate) {
|
||||
default:
|
||||
break;
|
||||
case 0: /*High density*/
|
||||
fdc->bit_rate = 500;
|
||||
break;
|
||||
case 1: /*Double density (360 rpm)*/
|
||||
switch (fdc->drvrate[drive]) {
|
||||
default:
|
||||
break;
|
||||
case 0:
|
||||
fdc->bit_rate = 300;
|
||||
break;
|
||||
case 1:
|
||||
fdc->bit_rate = 500;
|
||||
break;
|
||||
case 2:
|
||||
fdc->bit_rate = 2000;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2: /*Double density*/
|
||||
fdc->bit_rate = 250;
|
||||
break;
|
||||
case 3: /*Extended density*/
|
||||
fdc->bit_rate = 1000;
|
||||
break;
|
||||
}
|
||||
|
||||
fdc->bitcell_period = (1000000 / fdc->bit_rate) * 2; /*Bitcell period in ns*/
|
||||
}
|
||||
@@ -688,10 +692,6 @@ fdc_io_command_phase1(fdc_t *fdc, int out)
|
||||
fdc->stat |= 0x20;
|
||||
else
|
||||
dma_set_drq(fdc->dma_ch, 1);
|
||||
if (out)
|
||||
fdc->pos = 0;
|
||||
else
|
||||
fdc->inread = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -741,7 +741,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
|
||||
cycles -= ISA_CYCLES(8);
|
||||
|
||||
switch (addr & 7) {
|
||||
if (!fdc->power_down || ((addr & 7) == 2) || ((addr & 7) == 4)) switch (addr & 7) {
|
||||
case 0:
|
||||
return;
|
||||
case 1:
|
||||
@@ -776,14 +776,20 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->pnum = fdc->ptot = 0;
|
||||
}
|
||||
if ((val & 4) && !(fdc->dor & 4)) {
|
||||
timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC);
|
||||
fdc->interrupt = -1;
|
||||
fdc->perp &= 0xfc;
|
||||
if (fdc->power_down) {
|
||||
timer_set_delay_u64(&fdc->timer, 1000 * TIMER_USEC);
|
||||
fdc->interrupt = -5;
|
||||
} else {
|
||||
timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC);
|
||||
fdc->interrupt = -1;
|
||||
|
||||
for (i = 0; i < FDD_NUM; i++)
|
||||
ui_sb_update_icon(SB_FLOPPY | i, 0);
|
||||
fdc->perp &= 0xfc;
|
||||
|
||||
fdc_ctrl_reset(fdc);
|
||||
for (i = 0; i < FDD_NUM; i++)
|
||||
ui_sb_update_icon(SB_FLOPPY | i, 0);
|
||||
|
||||
fdc_ctrl_reset(fdc);
|
||||
}
|
||||
}
|
||||
/* We can now simplify this since each motor now spins separately. */
|
||||
for (i = 0; i < FDD_NUM; i++) {
|
||||
@@ -854,7 +860,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->pnum = 0;
|
||||
fdc->ptot = 4;
|
||||
fdc->stat |= 0x90;
|
||||
fdc->pos = 0;
|
||||
fdc->format_state = 0;
|
||||
} else
|
||||
fdc_bad_command(fdc);
|
||||
@@ -866,7 +871,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->pnum = 0;
|
||||
fdc->ptot = 8;
|
||||
fdc->stat |= 0x90;
|
||||
fdc->pos = 0;
|
||||
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
||||
break;
|
||||
case 0x03: /*Specify*/
|
||||
@@ -888,7 +892,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->pnum = 0;
|
||||
fdc->ptot = 8;
|
||||
fdc->stat |= 0x90;
|
||||
fdc->pos = 0;
|
||||
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
||||
break;
|
||||
case 0x06: /*Read data*/
|
||||
@@ -907,7 +910,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->pnum = 0;
|
||||
fdc->ptot = 8;
|
||||
fdc->stat |= 0x90;
|
||||
fdc->pos = 0;
|
||||
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
||||
break;
|
||||
case 0x17: /*Powerdown mode*/
|
||||
@@ -924,28 +926,24 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
case 0x08: /*Sense interrupt status*/
|
||||
fdc_log("fdc->fintr = %i, fdc->reset_stat = %i\n", fdc->fintr, fdc->reset_stat);
|
||||
fdc->lastdrive = fdc->drive;
|
||||
fdc->pos = 0;
|
||||
fdc_sis(fdc);
|
||||
break;
|
||||
case 0x0a: /*Read sector ID*/
|
||||
fdc->pnum = 0;
|
||||
fdc->ptot = 1;
|
||||
fdc->stat |= 0x90;
|
||||
fdc->pos = 0;
|
||||
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
||||
break;
|
||||
case 0x0d: /*Format track*/
|
||||
fdc->pnum = 0;
|
||||
fdc->ptot = 5;
|
||||
fdc->stat |= 0x90;
|
||||
fdc->pos = 0;
|
||||
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
||||
fdc->format_state = 0;
|
||||
break;
|
||||
case 0x0e: /*Dump registers*/
|
||||
fdc->lastdrive = fdc->drive;
|
||||
fdc->interrupt = 0x0e;
|
||||
fdc->pos = 0;
|
||||
fdc_callback(fdc);
|
||||
break;
|
||||
case 0x0f: /*Seek*/
|
||||
@@ -964,7 +962,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
case 0x94: /*Lock*/
|
||||
fdc->lastdrive = fdc->drive;
|
||||
fdc->interrupt = fdc->command;
|
||||
fdc->pos = 0;
|
||||
fdc_callback(fdc);
|
||||
break;
|
||||
case 0x12: /*Set perpendicular mode*/
|
||||
@@ -972,7 +969,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->pnum = 0;
|
||||
fdc->ptot = 1;
|
||||
fdc->stat |= 0x90;
|
||||
fdc->pos = 0;
|
||||
} else
|
||||
fdc_bad_command(fdc);
|
||||
break;
|
||||
@@ -980,7 +976,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->pnum = 0;
|
||||
fdc->ptot = 3;
|
||||
fdc->stat |= 0x90;
|
||||
fdc->pos = 0;
|
||||
break;
|
||||
default:
|
||||
fdc_bad_command(fdc);
|
||||
@@ -1151,7 +1146,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->format_sectors = fdc->params[2];
|
||||
fdc->format_n = fdc->params[1];
|
||||
fdc->format_state = 1;
|
||||
fdc->pos = 0;
|
||||
fdc->stat = 0x10;
|
||||
break;
|
||||
case 0x0f: /* Seek */
|
||||
@@ -1273,12 +1267,12 @@ uint8_t
|
||||
fdc_read(uint16_t addr, void *priv)
|
||||
{
|
||||
fdc_t *fdc = (fdc_t *) priv;
|
||||
uint8_t ret;
|
||||
uint8_t ret = 0xff;
|
||||
int drive = 0;
|
||||
|
||||
cycles -= ISA_CYCLES(8);
|
||||
|
||||
switch (addr & 7) {
|
||||
if (!fdc->power_down || ((addr & 7) == 2)) switch (addr & 7) {
|
||||
case 0: /* STA */
|
||||
if (fdc->flags & FDC_FLAG_PS1) {
|
||||
drive = real_drive(fdc, fdc->dor & 3);
|
||||
@@ -1513,7 +1507,6 @@ fdc_poll_readwrite_finish(fdc_t *fdc, int compare)
|
||||
if ((fdc->interrupt == 5) || (fdc->interrupt == 9))
|
||||
fdd_do_writeback(real_drive(fdc, fdc->drive));
|
||||
|
||||
fdc->inread = 0;
|
||||
fdc->interrupt = -2;
|
||||
|
||||
fdc_poll_common_finish(fdc, compare, 0);
|
||||
@@ -1544,10 +1537,21 @@ fdc_callback(void *priv)
|
||||
case -2: /*End of command*/
|
||||
fdc->stat = (fdc->stat & 0xf) | 0x80;
|
||||
return;
|
||||
case -5: /*Reset in power down mode */
|
||||
fdc->perp &= 0xfc;
|
||||
|
||||
for (uint8_t i = 0; i < FDD_NUM; i++)
|
||||
ui_sb_update_icon(SB_FLOPPY | i, 0);
|
||||
|
||||
fdc_ctrl_reset(fdc);
|
||||
|
||||
fdc->fintr = 0;
|
||||
memset(fdc->pcn, 0x00, 4 * sizeof(uint16_t));
|
||||
return;
|
||||
case -1: /*Reset*/
|
||||
fdc_int(fdc, 1);
|
||||
fdc->fintr = 0;
|
||||
memset(fdc->pcn, 0, 4 * sizeof(int));
|
||||
memset(fdc->pcn, 0x00, 4 * sizeof(uint16_t));
|
||||
fdc->reset_stat = 4;
|
||||
return;
|
||||
case 0x01: /* Mode */
|
||||
@@ -1570,7 +1574,6 @@ fdc_callback(void *priv)
|
||||
fdc->stat = 0x50;
|
||||
}
|
||||
}
|
||||
fdc->inread = 1;
|
||||
return;
|
||||
case 0x04: /* Sense drive status */
|
||||
fdc->res[10] = (fdc->params[0] & 7) | 0x20;
|
||||
@@ -1715,7 +1718,6 @@ fdc_callback(void *priv)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fdc->inread = 1;
|
||||
return;
|
||||
case 0x07: /* Recalibrate */
|
||||
fdc->pcn[fdc->params[0] & 3] = 0;
|
||||
@@ -2004,18 +2006,11 @@ fdc_data(fdc_t *fdc, uint8_t data, int last)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
fdc_finishread(fdc_t *fdc)
|
||||
{
|
||||
fdc->inread = 0;
|
||||
}
|
||||
|
||||
void
|
||||
fdc_track_finishread(fdc_t *fdc, int condition)
|
||||
{
|
||||
fdc->stat = 0x10;
|
||||
fdc->satisfying_sectors |= condition;
|
||||
fdc->inread = 0;
|
||||
fdc_callback(fdc);
|
||||
}
|
||||
|
||||
@@ -2025,7 +2020,6 @@ fdc_sector_finishcompare(fdc_t *fdc, int satisfying)
|
||||
fdc->stat = 0x10;
|
||||
if (satisfying)
|
||||
fdc->satisfying_sectors++;
|
||||
fdc->inread = 0;
|
||||
fdc_callback(fdc);
|
||||
}
|
||||
|
||||
@@ -2033,7 +2027,6 @@ void
|
||||
fdc_sector_finishread(fdc_t *fdc)
|
||||
{
|
||||
fdc->stat = 0x10;
|
||||
fdc->inread = 0;
|
||||
fdc_callback(fdc);
|
||||
}
|
||||
|
||||
@@ -2356,6 +2349,8 @@ fdc_reset(void *priv)
|
||||
|
||||
for (uint8_t i = 0; i < FDD_NUM; i++)
|
||||
ui_sb_update_icon(SB_FLOPPY | i, 0);
|
||||
|
||||
fdc->power_down = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2418,7 +2413,7 @@ fdc_init(const device_t *info)
|
||||
void
|
||||
fdc_3f1_enable(fdc_t *fdc, int enable)
|
||||
{
|
||||
fdc->enable_3f1 = enable;
|
||||
fdc->enable_3f1 = !!enable;
|
||||
}
|
||||
|
||||
const device_t fdc_xt_device = {
|
||||
|
||||
Reference in New Issue
Block a user