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->lock = 0;
|
||||||
fdc->head = 0;
|
fdc->head = 0;
|
||||||
fdc->step = 0;
|
fdc->step = 0;
|
||||||
|
fdc->power_down = 0;
|
||||||
if (!(fdc->flags & FDC_FLAG_AT))
|
if (!(fdc->flags & FDC_FLAG_AT))
|
||||||
fdc->rate = 2;
|
fdc->rate = 2;
|
||||||
}
|
}
|
||||||
@@ -257,7 +258,7 @@ fdc_set_wrong_am(fdc_t *fdc)
|
|||||||
int
|
int
|
||||||
fdc_get_drive(fdc_t *fdc)
|
fdc_get_drive(fdc_t *fdc)
|
||||||
{
|
{
|
||||||
return fdc->drive;
|
return (int) fdc->drive;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdc_get_bitcell_period(fdc_t *fdc);
|
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))
|
if (!(fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_PCJR))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return fdc->perp;
|
return (int) fdc->perp;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -292,7 +293,7 @@ fdc_get_gap2(fdc_t *fdc, int drive)
|
|||||||
int
|
int
|
||||||
fdc_get_format_n(fdc_t *fdc)
|
fdc_get_format_n(fdc_t *fdc)
|
||||||
{
|
{
|
||||||
return fdc->format_n;
|
return (int) fdc->format_n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -321,7 +322,7 @@ fdc_stop_id_request(fdc_t *fdc)
|
|||||||
int
|
int
|
||||||
fdc_get_gap(fdc_t *fdc)
|
fdc_get_gap(fdc_t *fdc)
|
||||||
{
|
{
|
||||||
return fdc->gap;
|
return (int) fdc->gap;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -333,7 +334,7 @@ fdc_get_dtl(fdc_t *fdc)
|
|||||||
int
|
int
|
||||||
fdc_get_format_sectors(fdc_t *fdc)
|
fdc_get_format_sectors(fdc_t *fdc)
|
||||||
{
|
{
|
||||||
return fdc->format_sectors;
|
return (int) fdc->format_sectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -418,6 +419,12 @@ fdc_update_rates(fdc_t *fdc)
|
|||||||
fdc_rate(fdc, 3);
|
fdc_rate(fdc, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fdc_set_power_down(fdc_t *fdc, uint8_t power_down)
|
||||||
|
{
|
||||||
|
fdc->power_down = power_down;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fdc_update_max_track(fdc_t *fdc, int max_track)
|
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
|
void
|
||||||
fdc_update_enh_mode(fdc_t *fdc, int enh_mode)
|
fdc_update_enh_mode(fdc_t *fdc, int enh_mode)
|
||||||
{
|
{
|
||||||
fdc->enh_mode = enh_mode;
|
fdc->enh_mode = !!enh_mode;
|
||||||
fdc_update_rates(fdc);
|
fdc_update_rates(fdc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,7 +497,7 @@ fdc_update_drvrate(fdc_t *fdc, int drive, int drvrate)
|
|||||||
void
|
void
|
||||||
fdc_update_drv2en(fdc_t *fdc, int drv2en)
|
fdc_update_drv2en(fdc_t *fdc, int drv2en)
|
||||||
{
|
{
|
||||||
fdc->drv2en = drv2en;
|
fdc->drv2en = !!drv2en;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -500,37 +507,34 @@ fdc_update_rate(fdc_t *fdc, int drive)
|
|||||||
fdc->bit_rate = 500;
|
fdc->bit_rate = 500;
|
||||||
else if ((fdc->rwc[drive] == 3) && fdc->enh_mode)
|
else if ((fdc->rwc[drive] == 3) && fdc->enh_mode)
|
||||||
fdc->bit_rate = 250;
|
fdc->bit_rate = 250;
|
||||||
else
|
else switch (fdc->rate) {
|
||||||
switch (fdc->rate) {
|
default:
|
||||||
case 0: /*High density*/
|
break;
|
||||||
fdc->bit_rate = 500;
|
case 0: /*High density*/
|
||||||
break;
|
fdc->bit_rate = 500;
|
||||||
case 1: /*Double density (360 rpm)*/
|
break;
|
||||||
switch (fdc->drvrate[drive]) {
|
case 1: /*Double density (360 rpm)*/
|
||||||
case 0:
|
switch (fdc->drvrate[drive]) {
|
||||||
fdc->bit_rate = 300;
|
default:
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 0:
|
||||||
fdc->bit_rate = 500;
|
fdc->bit_rate = 300;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 1:
|
||||||
fdc->bit_rate = 2000;
|
fdc->bit_rate = 500;
|
||||||
break;
|
break;
|
||||||
|
case 2:
|
||||||
default:
|
fdc->bit_rate = 2000;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2: /*Double density*/
|
case 2: /*Double density*/
|
||||||
fdc->bit_rate = 250;
|
fdc->bit_rate = 250;
|
||||||
break;
|
break;
|
||||||
case 3: /*Extended density*/
|
case 3: /*Extended density*/
|
||||||
fdc->bit_rate = 1000;
|
fdc->bit_rate = 1000;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
fdc->bitcell_period = (1000000 / fdc->bit_rate) * 2; /*Bitcell period in ns*/
|
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;
|
fdc->stat |= 0x20;
|
||||||
else
|
else
|
||||||
dma_set_drq(fdc->dma_ch, 1);
|
dma_set_drq(fdc->dma_ch, 1);
|
||||||
if (out)
|
|
||||||
fdc->pos = 0;
|
|
||||||
else
|
|
||||||
fdc->inread = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -741,7 +741,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||||||
|
|
||||||
cycles -= ISA_CYCLES(8);
|
cycles -= ISA_CYCLES(8);
|
||||||
|
|
||||||
switch (addr & 7) {
|
if (!fdc->power_down || ((addr & 7) == 2) || ((addr & 7) == 4)) switch (addr & 7) {
|
||||||
case 0:
|
case 0:
|
||||||
return;
|
return;
|
||||||
case 1:
|
case 1:
|
||||||
@@ -776,14 +776,20 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||||||
fdc->pnum = fdc->ptot = 0;
|
fdc->pnum = fdc->ptot = 0;
|
||||||
}
|
}
|
||||||
if ((val & 4) && !(fdc->dor & 4)) {
|
if ((val & 4) && !(fdc->dor & 4)) {
|
||||||
timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC);
|
if (fdc->power_down) {
|
||||||
fdc->interrupt = -1;
|
timer_set_delay_u64(&fdc->timer, 1000 * TIMER_USEC);
|
||||||
fdc->perp &= 0xfc;
|
fdc->interrupt = -5;
|
||||||
|
} else {
|
||||||
|
timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC);
|
||||||
|
fdc->interrupt = -1;
|
||||||
|
|
||||||
for (i = 0; i < FDD_NUM; i++)
|
fdc->perp &= 0xfc;
|
||||||
ui_sb_update_icon(SB_FLOPPY | i, 0);
|
|
||||||
|
|
||||||
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. */
|
/* We can now simplify this since each motor now spins separately. */
|
||||||
for (i = 0; i < FDD_NUM; i++) {
|
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->pnum = 0;
|
||||||
fdc->ptot = 4;
|
fdc->ptot = 4;
|
||||||
fdc->stat |= 0x90;
|
fdc->stat |= 0x90;
|
||||||
fdc->pos = 0;
|
|
||||||
fdc->format_state = 0;
|
fdc->format_state = 0;
|
||||||
} else
|
} else
|
||||||
fdc_bad_command(fdc);
|
fdc_bad_command(fdc);
|
||||||
@@ -866,7 +871,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||||||
fdc->pnum = 0;
|
fdc->pnum = 0;
|
||||||
fdc->ptot = 8;
|
fdc->ptot = 8;
|
||||||
fdc->stat |= 0x90;
|
fdc->stat |= 0x90;
|
||||||
fdc->pos = 0;
|
|
||||||
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
||||||
break;
|
break;
|
||||||
case 0x03: /*Specify*/
|
case 0x03: /*Specify*/
|
||||||
@@ -888,7 +892,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||||||
fdc->pnum = 0;
|
fdc->pnum = 0;
|
||||||
fdc->ptot = 8;
|
fdc->ptot = 8;
|
||||||
fdc->stat |= 0x90;
|
fdc->stat |= 0x90;
|
||||||
fdc->pos = 0;
|
|
||||||
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
||||||
break;
|
break;
|
||||||
case 0x06: /*Read data*/
|
case 0x06: /*Read data*/
|
||||||
@@ -907,7 +910,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||||||
fdc->pnum = 0;
|
fdc->pnum = 0;
|
||||||
fdc->ptot = 8;
|
fdc->ptot = 8;
|
||||||
fdc->stat |= 0x90;
|
fdc->stat |= 0x90;
|
||||||
fdc->pos = 0;
|
|
||||||
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
||||||
break;
|
break;
|
||||||
case 0x17: /*Powerdown mode*/
|
case 0x17: /*Powerdown mode*/
|
||||||
@@ -924,28 +926,24 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||||||
case 0x08: /*Sense interrupt status*/
|
case 0x08: /*Sense interrupt status*/
|
||||||
fdc_log("fdc->fintr = %i, fdc->reset_stat = %i\n", fdc->fintr, fdc->reset_stat);
|
fdc_log("fdc->fintr = %i, fdc->reset_stat = %i\n", fdc->fintr, fdc->reset_stat);
|
||||||
fdc->lastdrive = fdc->drive;
|
fdc->lastdrive = fdc->drive;
|
||||||
fdc->pos = 0;
|
|
||||||
fdc_sis(fdc);
|
fdc_sis(fdc);
|
||||||
break;
|
break;
|
||||||
case 0x0a: /*Read sector ID*/
|
case 0x0a: /*Read sector ID*/
|
||||||
fdc->pnum = 0;
|
fdc->pnum = 0;
|
||||||
fdc->ptot = 1;
|
fdc->ptot = 1;
|
||||||
fdc->stat |= 0x90;
|
fdc->stat |= 0x90;
|
||||||
fdc->pos = 0;
|
|
||||||
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
||||||
break;
|
break;
|
||||||
case 0x0d: /*Format track*/
|
case 0x0d: /*Format track*/
|
||||||
fdc->pnum = 0;
|
fdc->pnum = 0;
|
||||||
fdc->ptot = 5;
|
fdc->ptot = 5;
|
||||||
fdc->stat |= 0x90;
|
fdc->stat |= 0x90;
|
||||||
fdc->pos = 0;
|
|
||||||
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
fdc->mfm = (fdc->command & 0x40) ? 1 : 0;
|
||||||
fdc->format_state = 0;
|
fdc->format_state = 0;
|
||||||
break;
|
break;
|
||||||
case 0x0e: /*Dump registers*/
|
case 0x0e: /*Dump registers*/
|
||||||
fdc->lastdrive = fdc->drive;
|
fdc->lastdrive = fdc->drive;
|
||||||
fdc->interrupt = 0x0e;
|
fdc->interrupt = 0x0e;
|
||||||
fdc->pos = 0;
|
|
||||||
fdc_callback(fdc);
|
fdc_callback(fdc);
|
||||||
break;
|
break;
|
||||||
case 0x0f: /*Seek*/
|
case 0x0f: /*Seek*/
|
||||||
@@ -964,7 +962,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||||||
case 0x94: /*Lock*/
|
case 0x94: /*Lock*/
|
||||||
fdc->lastdrive = fdc->drive;
|
fdc->lastdrive = fdc->drive;
|
||||||
fdc->interrupt = fdc->command;
|
fdc->interrupt = fdc->command;
|
||||||
fdc->pos = 0;
|
|
||||||
fdc_callback(fdc);
|
fdc_callback(fdc);
|
||||||
break;
|
break;
|
||||||
case 0x12: /*Set perpendicular mode*/
|
case 0x12: /*Set perpendicular mode*/
|
||||||
@@ -972,7 +969,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||||||
fdc->pnum = 0;
|
fdc->pnum = 0;
|
||||||
fdc->ptot = 1;
|
fdc->ptot = 1;
|
||||||
fdc->stat |= 0x90;
|
fdc->stat |= 0x90;
|
||||||
fdc->pos = 0;
|
|
||||||
} else
|
} else
|
||||||
fdc_bad_command(fdc);
|
fdc_bad_command(fdc);
|
||||||
break;
|
break;
|
||||||
@@ -980,7 +976,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||||||
fdc->pnum = 0;
|
fdc->pnum = 0;
|
||||||
fdc->ptot = 3;
|
fdc->ptot = 3;
|
||||||
fdc->stat |= 0x90;
|
fdc->stat |= 0x90;
|
||||||
fdc->pos = 0;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fdc_bad_command(fdc);
|
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_sectors = fdc->params[2];
|
||||||
fdc->format_n = fdc->params[1];
|
fdc->format_n = fdc->params[1];
|
||||||
fdc->format_state = 1;
|
fdc->format_state = 1;
|
||||||
fdc->pos = 0;
|
|
||||||
fdc->stat = 0x10;
|
fdc->stat = 0x10;
|
||||||
break;
|
break;
|
||||||
case 0x0f: /* Seek */
|
case 0x0f: /* Seek */
|
||||||
@@ -1273,12 +1267,12 @@ uint8_t
|
|||||||
fdc_read(uint16_t addr, void *priv)
|
fdc_read(uint16_t addr, void *priv)
|
||||||
{
|
{
|
||||||
fdc_t *fdc = (fdc_t *) priv;
|
fdc_t *fdc = (fdc_t *) priv;
|
||||||
uint8_t ret;
|
uint8_t ret = 0xff;
|
||||||
int drive = 0;
|
int drive = 0;
|
||||||
|
|
||||||
cycles -= ISA_CYCLES(8);
|
cycles -= ISA_CYCLES(8);
|
||||||
|
|
||||||
switch (addr & 7) {
|
if (!fdc->power_down || ((addr & 7) == 2)) switch (addr & 7) {
|
||||||
case 0: /* STA */
|
case 0: /* STA */
|
||||||
if (fdc->flags & FDC_FLAG_PS1) {
|
if (fdc->flags & FDC_FLAG_PS1) {
|
||||||
drive = real_drive(fdc, fdc->dor & 3);
|
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))
|
if ((fdc->interrupt == 5) || (fdc->interrupt == 9))
|
||||||
fdd_do_writeback(real_drive(fdc, fdc->drive));
|
fdd_do_writeback(real_drive(fdc, fdc->drive));
|
||||||
|
|
||||||
fdc->inread = 0;
|
|
||||||
fdc->interrupt = -2;
|
fdc->interrupt = -2;
|
||||||
|
|
||||||
fdc_poll_common_finish(fdc, compare, 0);
|
fdc_poll_common_finish(fdc, compare, 0);
|
||||||
@@ -1544,10 +1537,21 @@ fdc_callback(void *priv)
|
|||||||
case -2: /*End of command*/
|
case -2: /*End of command*/
|
||||||
fdc->stat = (fdc->stat & 0xf) | 0x80;
|
fdc->stat = (fdc->stat & 0xf) | 0x80;
|
||||||
return;
|
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*/
|
case -1: /*Reset*/
|
||||||
fdc_int(fdc, 1);
|
fdc_int(fdc, 1);
|
||||||
fdc->fintr = 0;
|
fdc->fintr = 0;
|
||||||
memset(fdc->pcn, 0, 4 * sizeof(int));
|
memset(fdc->pcn, 0x00, 4 * sizeof(uint16_t));
|
||||||
fdc->reset_stat = 4;
|
fdc->reset_stat = 4;
|
||||||
return;
|
return;
|
||||||
case 0x01: /* Mode */
|
case 0x01: /* Mode */
|
||||||
@@ -1570,7 +1574,6 @@ fdc_callback(void *priv)
|
|||||||
fdc->stat = 0x50;
|
fdc->stat = 0x50;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fdc->inread = 1;
|
|
||||||
return;
|
return;
|
||||||
case 0x04: /* Sense drive status */
|
case 0x04: /* Sense drive status */
|
||||||
fdc->res[10] = (fdc->params[0] & 7) | 0x20;
|
fdc->res[10] = (fdc->params[0] & 7) | 0x20;
|
||||||
@@ -1715,7 +1718,6 @@ fdc_callback(void *priv)
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fdc->inread = 1;
|
|
||||||
return;
|
return;
|
||||||
case 0x07: /* Recalibrate */
|
case 0x07: /* Recalibrate */
|
||||||
fdc->pcn[fdc->params[0] & 3] = 0;
|
fdc->pcn[fdc->params[0] & 3] = 0;
|
||||||
@@ -2004,18 +2006,11 @@ fdc_data(fdc_t *fdc, uint8_t data, int last)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
fdc_finishread(fdc_t *fdc)
|
|
||||||
{
|
|
||||||
fdc->inread = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
fdc_track_finishread(fdc_t *fdc, int condition)
|
fdc_track_finishread(fdc_t *fdc, int condition)
|
||||||
{
|
{
|
||||||
fdc->stat = 0x10;
|
fdc->stat = 0x10;
|
||||||
fdc->satisfying_sectors |= condition;
|
fdc->satisfying_sectors |= condition;
|
||||||
fdc->inread = 0;
|
|
||||||
fdc_callback(fdc);
|
fdc_callback(fdc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2025,7 +2020,6 @@ fdc_sector_finishcompare(fdc_t *fdc, int satisfying)
|
|||||||
fdc->stat = 0x10;
|
fdc->stat = 0x10;
|
||||||
if (satisfying)
|
if (satisfying)
|
||||||
fdc->satisfying_sectors++;
|
fdc->satisfying_sectors++;
|
||||||
fdc->inread = 0;
|
|
||||||
fdc_callback(fdc);
|
fdc_callback(fdc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2033,7 +2027,6 @@ void
|
|||||||
fdc_sector_finishread(fdc_t *fdc)
|
fdc_sector_finishread(fdc_t *fdc)
|
||||||
{
|
{
|
||||||
fdc->stat = 0x10;
|
fdc->stat = 0x10;
|
||||||
fdc->inread = 0;
|
|
||||||
fdc_callback(fdc);
|
fdc_callback(fdc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2356,6 +2349,8 @@ fdc_reset(void *priv)
|
|||||||
|
|
||||||
for (uint8_t i = 0; i < FDD_NUM; i++)
|
for (uint8_t i = 0; i < FDD_NUM; i++)
|
||||||
ui_sb_update_icon(SB_FLOPPY | i, 0);
|
ui_sb_update_icon(SB_FLOPPY | i, 0);
|
||||||
|
|
||||||
|
fdc->power_down = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -2418,7 +2413,7 @@ fdc_init(const device_t *info)
|
|||||||
void
|
void
|
||||||
fdc_3f1_enable(fdc_t *fdc, int enable)
|
fdc_3f1_enable(fdc_t *fdc, int enable)
|
||||||
{
|
{
|
||||||
fdc->enable_3f1 = enable;
|
fdc->enable_3f1 = !!enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
const device_t fdc_xt_device = {
|
const device_t fdc_xt_device = {
|
||||||
|
|||||||
@@ -1274,18 +1274,19 @@ d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, ui
|
|||||||
if (dev->last_word[side] == req_am) {
|
if (dev->last_word[side] == req_am) {
|
||||||
dev->calc_crc.word = 0xFFFF;
|
dev->calc_crc.word = 0xFFFF;
|
||||||
fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc));
|
fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc));
|
||||||
find->sync_marks = find->bits_obtained = find->bytes_obtained = 0;
|
find->sync_marks = find->bits_obtained =
|
||||||
find->sync_pos = 0xFFFFFFFF;
|
find->bytes_obtained = 0;
|
||||||
dev->preceding_bit[side] = dev->last_word[side] & 1;
|
find->sync_pos = 0xFFFFFFFF;
|
||||||
|
dev->preceding_bit[side] = dev->last_word[side] & 1;
|
||||||
dev->state++;
|
dev->state++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wrong_am && (dev->last_word[side] == wrong_am)) {
|
if (wrong_am && (dev->last_word[side] == wrong_am)) {
|
||||||
dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0;
|
dev->data_find.sync_marks = dev->data_find.bits_obtained =
|
||||||
dev->error_condition = 0;
|
dev->data_find.bytes_obtained = 0;
|
||||||
dev->state = STATE_IDLE;
|
dev->error_condition = 0;
|
||||||
fdc_finishread(d86f_fdc);
|
dev->state = STATE_IDLE;
|
||||||
fdc_nodataam(d86f_fdc);
|
fdc_nodataam(d86f_fdc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1328,8 +1329,9 @@ d86f_write_find_address_mark_fm(int drive, int side, find_t *find)
|
|||||||
|
|
||||||
/* If we hadn't found enough set bits but have found a clear bit, null the counter of set bits. */
|
/* If we hadn't found enough set bits but have found a clear bit, null the counter of set bits. */
|
||||||
if (!(dev->last_word[side] & 1)) {
|
if (!(dev->last_word[side] & 1)) {
|
||||||
find->sync_marks = find->bits_obtained = find->bytes_obtained = 0;
|
find->sync_marks = find->bits_obtained =
|
||||||
find->sync_pos = 0xFFFFFFFF;
|
find->bytes_obtained = 0;
|
||||||
|
find->sync_pos = 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1347,10 +1349,10 @@ d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, u
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (wrong_am && (dev->last_word[side] == wrong_am) && (find->sync_marks >= 3)) {
|
if (wrong_am && (dev->last_word[side] == wrong_am) && (find->sync_marks >= 3)) {
|
||||||
dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0;
|
dev->data_find.sync_marks = dev->data_find.bits_obtained =
|
||||||
dev->error_condition = 0;
|
dev->data_find.bytes_obtained = 0;
|
||||||
dev->state = STATE_IDLE;
|
dev->error_condition = 0;
|
||||||
fdc_finishread(d86f_fdc);
|
dev->state = STATE_IDLE;
|
||||||
fdc_nodataam(d86f_fdc);
|
fdc_nodataam(d86f_fdc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1433,22 +1435,26 @@ d86f_read_sector_id(int drive, int side, int match)
|
|||||||
if (!(dev->id_find.bits_obtained & 15)) {
|
if (!(dev->id_find.bits_obtained & 15)) {
|
||||||
/* We've got a byte. */
|
/* We've got a byte. */
|
||||||
if (dev->id_find.bytes_obtained < 4) {
|
if (dev->id_find.bytes_obtained < 4) {
|
||||||
dev->last_sector.byte_array[dev->id_find.bytes_obtained] = decodefm(drive, dev->last_word[side]);
|
dev->last_sector.byte_array[dev->id_find.bytes_obtained] =
|
||||||
|
decodefm(drive, dev->last_word[side]);
|
||||||
fdd_calccrc(dev->last_sector.byte_array[dev->id_find.bytes_obtained], &(dev->calc_crc));
|
fdd_calccrc(dev->last_sector.byte_array[dev->id_find.bytes_obtained], &(dev->calc_crc));
|
||||||
} else if ((dev->id_find.bytes_obtained >= 4) && (dev->id_find.bytes_obtained < 6)) {
|
} else if ((dev->id_find.bytes_obtained >= 4) && (dev->id_find.bytes_obtained < 6)) {
|
||||||
dev->track_crc.bytes[(dev->id_find.bytes_obtained & 1) ^ 1] = decodefm(drive, dev->last_word[side]);
|
dev->track_crc.bytes[(dev->id_find.bytes_obtained & 1) ^ 1] =
|
||||||
|
decodefm(drive, dev->last_word[side]);
|
||||||
}
|
}
|
||||||
dev->id_find.bytes_obtained++;
|
dev->id_find.bytes_obtained++;
|
||||||
|
|
||||||
if (dev->id_find.bytes_obtained == 6) {
|
if (dev->id_find.bytes_obtained == 6) {
|
||||||
/* We've got the ID. */
|
/* We've got the ID. */
|
||||||
if ((dev->calc_crc.word != dev->track_crc.word) && (dev->last_sector.dword == dev->req_sector.dword)) {
|
if ((dev->calc_crc.word != dev->track_crc.word) &&
|
||||||
dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0;
|
(dev->last_sector.dword == dev->req_sector.dword)) {
|
||||||
d86f_log("86F: ID CRC error: %04X != %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword);
|
dev->id_find.sync_marks = dev->id_find.bits_obtained =
|
||||||
|
dev->id_find.bytes_obtained = 0;
|
||||||
|
d86f_log("86F: ID CRC error: %04X != %04X (%08X)\n", dev->track_crc.word,
|
||||||
|
dev->calc_crc.word, dev->last_sector.dword);
|
||||||
if ((dev->state != STATE_02_READ_ID) && (dev->state != STATE_0A_READ_ID)) {
|
if ((dev->state != STATE_02_READ_ID) && (dev->state != STATE_0A_READ_ID)) {
|
||||||
dev->error_condition = 0;
|
dev->error_condition = 0;
|
||||||
dev->state = STATE_IDLE;
|
dev->state = STATE_IDLE;
|
||||||
fdc_finishread(d86f_fdc);
|
|
||||||
fdc_headercrcerror(d86f_fdc);
|
fdc_headercrcerror(d86f_fdc);
|
||||||
} else if (dev->state == STATE_0A_READ_ID)
|
} else if (dev->state == STATE_0A_READ_ID)
|
||||||
dev->state--;
|
dev->state--;
|
||||||
@@ -1458,25 +1464,37 @@ d86f_read_sector_id(int drive, int side, int match)
|
|||||||
}
|
}
|
||||||
} else if ((dev->calc_crc.word == dev->track_crc.word) && (dev->state == STATE_0A_READ_ID)) {
|
} else if ((dev->calc_crc.word == dev->track_crc.word) && (dev->state == STATE_0A_READ_ID)) {
|
||||||
/* CRC is valid and this is a read sector ID command. */
|
/* CRC is valid and this is a read sector ID command. */
|
||||||
dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0;
|
dev->id_find.sync_marks = dev->id_find.bits_obtained =
|
||||||
fdc_sectorid(d86f_fdc, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n, 0, 0);
|
dev->id_find.bytes_obtained = dev->error_condition = 0;
|
||||||
|
fdc_sectorid(d86f_fdc,
|
||||||
|
dev->last_sector.id.c, dev->last_sector.id.h,
|
||||||
|
dev->last_sector.id.r, dev->last_sector.id.n, 0, 0);
|
||||||
dev->state = STATE_IDLE;
|
dev->state = STATE_IDLE;
|
||||||
} else {
|
} else {
|
||||||
/* CRC is valid. */
|
/* CRC is valid. */
|
||||||
dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0;
|
dev->id_find.sync_marks = dev->id_find.bits_obtained =
|
||||||
|
dev->id_find.bytes_obtained = 0;
|
||||||
dev->id_found |= 1;
|
dev->id_found |= 1;
|
||||||
if ((dev->last_sector.dword == dev->req_sector.dword) || !match) {
|
if ((dev->last_sector.dword == dev->req_sector.dword) || !match) {
|
||||||
d86f_handler[drive].set_sector(drive, side, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n);
|
d86f_handler[drive].set_sector(drive, side,
|
||||||
|
dev->last_sector.id.c, dev->last_sector.id.h,
|
||||||
|
dev->last_sector.id.r, dev->last_sector.id.n);
|
||||||
if (dev->state == STATE_02_READ_ID) {
|
if (dev->state == STATE_02_READ_ID) {
|
||||||
/* READ TRACK command, we need some special handling here. */
|
/* READ TRACK command, we need some special handling here. */
|
||||||
/* Code corrected: Only the C, H, and N portions of the sector ID are compared, the R portion (the sector number) is ignored. */
|
/* Code corrected: Only the C, H, and N portions of the
|
||||||
if ((dev->last_sector.id.c != fdc_get_read_track_sector(d86f_fdc).id.c) || (dev->last_sector.id.h != fdc_get_read_track_sector(d86f_fdc).id.h) || (dev->last_sector.id.n != fdc_get_read_track_sector(d86f_fdc).id.n)) {
|
sector ID are compared, the R portion
|
||||||
dev->error_condition |= 4; /* Mark that the sector ID is not the one expected by the FDC. */
|
(the sector number) is ignored. */
|
||||||
|
if ((dev->last_sector.id.c != fdc_get_read_track_sector(d86f_fdc).id.c) ||
|
||||||
|
(dev->last_sector.id.h != fdc_get_read_track_sector(d86f_fdc).id.h) ||
|
||||||
|
(dev->last_sector.id.n != fdc_get_read_track_sector(d86f_fdc).id.n)) {
|
||||||
|
/* Mark that the sector ID is not the one expected by the FDC. */
|
||||||
|
dev->error_condition |= 4;
|
||||||
/* Make sure we use the sector size from the FDC. */
|
/* Make sure we use the sector size from the FDC. */
|
||||||
dev->last_sector.id.n = fdc_get_read_track_sector(d86f_fdc).id.n;
|
dev->last_sector.id.n = fdc_get_read_track_sector(d86f_fdc).id.n;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the two ID's are identical, then we do not need to do anything regarding the sector size. */
|
/* If the two ID's are identical, then we do not need to do
|
||||||
|
anything regarding the sector size. */
|
||||||
}
|
}
|
||||||
dev->state++;
|
dev->state++;
|
||||||
} else {
|
} else {
|
||||||
@@ -1576,7 +1594,8 @@ d86f_read_sector_data(int drive, int side)
|
|||||||
data = d86f_handler[drive].read_data(drive, side, dev->data_find.bytes_obtained);
|
data = d86f_handler[drive].read_data(drive, side, dev->data_find.bytes_obtained);
|
||||||
else {
|
else {
|
||||||
#ifdef HACK_FOR_DBASE_III
|
#ifdef HACK_FOR_DBASE_III
|
||||||
if ((dev->last_sector.id.c == 39) && (dev->last_sector.id.h == 0) && (dev->last_sector.id.r == 5) && (dev->data_find.bytes_obtained >= 272))
|
if ((dev->last_sector.id.c == 39) && (dev->last_sector.id.h == 0) &&
|
||||||
|
(dev->last_sector.id.r == 5) && (dev->data_find.bytes_obtained >= 272))
|
||||||
data = (random_generate() & 0xff);
|
data = (random_generate() & 0xff);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@@ -1589,7 +1608,9 @@ d86f_read_sector_data(int drive, int side)
|
|||||||
} else {
|
} else {
|
||||||
if (dev->data_find.bytes_obtained < d86f_get_data_len(drive)) {
|
if (dev->data_find.bytes_obtained < d86f_get_data_len(drive)) {
|
||||||
if (dev->state != STATE_16_VERIFY_DATA) {
|
if (dev->state != STATE_16_VERIFY_DATA) {
|
||||||
read_status = fdc_data(d86f_fdc, data, dev->data_find.bytes_obtained == (d86f_get_data_len(drive) - 1));
|
read_status = fdc_data(d86f_fdc, data,
|
||||||
|
dev->data_find.bytes_obtained ==
|
||||||
|
(d86f_get_data_len(drive) - 1));
|
||||||
if (read_status == -1)
|
if (read_status == -1)
|
||||||
dev->dma_over++;
|
dev->dma_over++;
|
||||||
}
|
}
|
||||||
@@ -1597,17 +1618,19 @@ d86f_read_sector_data(int drive, int side)
|
|||||||
}
|
}
|
||||||
fdd_calccrc(data, &(dev->calc_crc));
|
fdd_calccrc(data, &(dev->calc_crc));
|
||||||
} else if (dev->data_find.bytes_obtained < crc_pos)
|
} else if (dev->data_find.bytes_obtained < crc_pos)
|
||||||
dev->track_crc.bytes[(dev->data_find.bytes_obtained - sector_len) ^ 1] = decodefm(drive, dev->last_word[side]);
|
dev->track_crc.bytes[(dev->data_find.bytes_obtained - sector_len) ^ 1] =
|
||||||
|
decodefm(drive, dev->last_word[side]);
|
||||||
dev->data_find.bytes_obtained++;
|
dev->data_find.bytes_obtained++;
|
||||||
|
|
||||||
if (dev->data_find.bytes_obtained == (crc_pos + fdc_get_gap(d86f_fdc))) {
|
if (dev->data_find.bytes_obtained == (crc_pos + fdc_get_gap(d86f_fdc))) {
|
||||||
/* We've got the data. */
|
/* We've got the data. */
|
||||||
if ((dev->calc_crc.word != dev->track_crc.word) && (dev->state != STATE_02_READ_DATA)) {
|
if ((dev->calc_crc.word != dev->track_crc.word) && (dev->state != STATE_02_READ_DATA)) {
|
||||||
d86f_log("86F: Data CRC error: %04X != %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword);
|
d86f_log("86F: Data CRC error: %04X != %04X (%08X)\n", dev->track_crc.word,
|
||||||
dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0;
|
dev->calc_crc.word, dev->last_sector.dword);
|
||||||
dev->error_condition = 0;
|
dev->data_find.sync_marks = dev->data_find.bits_obtained =
|
||||||
dev->state = STATE_IDLE;
|
dev->data_find.bytes_obtained = 0;
|
||||||
fdc_finishread(d86f_fdc);
|
dev->error_condition = 0;
|
||||||
|
dev->state = STATE_IDLE;
|
||||||
fdc_datacrcerror(d86f_fdc);
|
fdc_datacrcerror(d86f_fdc);
|
||||||
} else if ((dev->calc_crc.word != dev->track_crc.word) && (dev->state == STATE_02_READ_DATA)) {
|
} else if ((dev->calc_crc.word != dev->track_crc.word) && (dev->state == STATE_02_READ_DATA)) {
|
||||||
dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0;
|
dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0;
|
||||||
@@ -2146,7 +2169,8 @@ d86f_turbo_read(int drive, int side)
|
|||||||
} else {
|
} else {
|
||||||
if (dev->turbo_pos < (128UL << dev->req_sector.id.n)) {
|
if (dev->turbo_pos < (128UL << dev->req_sector.id.n)) {
|
||||||
if (dev->state != STATE_16_VERIFY_DATA) {
|
if (dev->state != STATE_16_VERIFY_DATA) {
|
||||||
read_status = fdc_data(d86f_fdc, dat, dev->turbo_pos == ((128UL << dev->req_sector.id.n) - 1));
|
read_status = fdc_data(d86f_fdc, dat,
|
||||||
|
dev->turbo_pos == ((128UL << dev->req_sector.id.n) - 1));
|
||||||
if (read_status == -1)
|
if (read_status == -1)
|
||||||
dev->dma_over++;
|
dev->dma_over++;
|
||||||
}
|
}
|
||||||
@@ -2163,7 +2187,6 @@ d86f_turbo_read(int drive, int side)
|
|||||||
#endif
|
#endif
|
||||||
dev->error_condition = 0;
|
dev->error_condition = 0;
|
||||||
dev->state = STATE_IDLE;
|
dev->state = STATE_IDLE;
|
||||||
fdc_finishread(d86f_fdc);
|
|
||||||
fdc_datacrcerror(d86f_fdc);
|
fdc_datacrcerror(d86f_fdc);
|
||||||
} else if ((flags & SECTOR_CRC_ERROR) && (dev->state == STATE_02_READ_DATA)) {
|
} else if ((flags & SECTOR_CRC_ERROR) && (dev->state == STATE_02_READ_DATA)) {
|
||||||
#ifdef ENABLE_D86F_LOG
|
#ifdef ENABLE_D86F_LOG
|
||||||
|
|||||||
@@ -65,76 +65,85 @@ typedef struct fdc_t {
|
|||||||
uint8_t st0;
|
uint8_t st0;
|
||||||
uint8_t swap;
|
uint8_t swap;
|
||||||
uint8_t dtl;
|
uint8_t dtl;
|
||||||
|
|
||||||
uint8_t swwp;
|
uint8_t swwp;
|
||||||
uint8_t disable_write;
|
uint8_t disable_write;
|
||||||
uint8_t st5;
|
uint8_t st5;
|
||||||
uint8_t st6;
|
uint8_t st6;
|
||||||
uint8_t error;
|
uint8_t error;
|
||||||
uint8_t params[8];
|
|
||||||
uint8_t res[11];
|
|
||||||
uint8_t specify[2];
|
|
||||||
uint8_t config;
|
uint8_t config;
|
||||||
uint8_t pretrk;
|
uint8_t pretrk;
|
||||||
|
uint8_t power_down;
|
||||||
|
|
||||||
|
uint8_t head;
|
||||||
|
uint8_t lastdrive;
|
||||||
|
uint8_t sector;
|
||||||
|
uint8_t drive;
|
||||||
|
uint8_t rate;
|
||||||
|
uint8_t tc;
|
||||||
|
uint8_t pnum;
|
||||||
|
uint8_t ptot;
|
||||||
|
|
||||||
|
uint8_t reset_stat;
|
||||||
|
uint8_t seek_dir;
|
||||||
|
uint8_t perp;
|
||||||
|
uint8_t format_state;
|
||||||
|
uint8_t format_n;
|
||||||
|
uint8_t step;
|
||||||
|
uint8_t noprec;
|
||||||
|
uint8_t data_ready;
|
||||||
|
|
||||||
|
uint8_t paramstogo;
|
||||||
|
uint8_t enh_mode;
|
||||||
|
uint8_t dma;
|
||||||
|
uint8_t densel_polarity;
|
||||||
|
uint8_t densel_force;
|
||||||
|
uint8_t fifo;
|
||||||
|
uint8_t tfifo;
|
||||||
|
uint8_t fifobufpos;
|
||||||
|
|
||||||
|
uint8_t drv2en;
|
||||||
|
uint8_t gap;
|
||||||
|
uint8_t enable_3f1;
|
||||||
|
uint8_t format_sectors;
|
||||||
|
uint8_t mfm;
|
||||||
|
uint8_t deleted;
|
||||||
|
uint8_t wrong_am;
|
||||||
|
uint8_t sc;
|
||||||
|
|
||||||
|
uint8_t fintr;
|
||||||
|
uint8_t rw_drive;
|
||||||
|
|
||||||
|
uint8_t lock;
|
||||||
|
uint8_t specify[2];
|
||||||
|
|
||||||
|
uint8_t res[11];
|
||||||
|
|
||||||
|
uint8_t eot[4];
|
||||||
|
uint8_t rwc[4];
|
||||||
|
uint8_t params[8];
|
||||||
uint8_t fifobuf[16];
|
uint8_t fifobuf[16];
|
||||||
|
|
||||||
|
uint16_t pcn[4];
|
||||||
|
|
||||||
uint16_t base_address;
|
uint16_t base_address;
|
||||||
|
uint16_t rw_track;
|
||||||
|
|
||||||
int head;
|
int bit_rate; /* Should be 250 at start. */
|
||||||
int sector;
|
|
||||||
int drive;
|
|
||||||
int lastdrive;
|
|
||||||
int pcn[4];
|
|
||||||
int eot[4];
|
|
||||||
int rw_track;
|
|
||||||
int pos;
|
|
||||||
int pnum;
|
|
||||||
int ptot;
|
|
||||||
int rate;
|
|
||||||
int reset_stat;
|
|
||||||
int lock;
|
|
||||||
int perp;
|
|
||||||
int format_state;
|
|
||||||
int format_n;
|
|
||||||
int step;
|
|
||||||
int seek_dir;
|
|
||||||
int tc;
|
|
||||||
int noprec;
|
|
||||||
|
|
||||||
int data_ready;
|
|
||||||
int inread;
|
|
||||||
int bitcell_period;
|
int bitcell_period;
|
||||||
int enh_mode;
|
|
||||||
int rwc[4];
|
|
||||||
int drvrate[4];
|
|
||||||
int boot_drive;
|
int boot_drive;
|
||||||
int dma;
|
|
||||||
int densel_polarity;
|
|
||||||
int densel_force;
|
|
||||||
int fifo;
|
|
||||||
int tfifo;
|
|
||||||
int fifobufpos;
|
|
||||||
int drv2en;
|
|
||||||
|
|
||||||
int gap;
|
|
||||||
int enable_3f1;
|
|
||||||
int format_sectors;
|
|
||||||
int max_track;
|
int max_track;
|
||||||
int mfm;
|
|
||||||
int deleted;
|
|
||||||
int wrong_am;
|
|
||||||
int sc;
|
|
||||||
int satisfying_sectors;
|
int satisfying_sectors;
|
||||||
int fintr;
|
|
||||||
int rw_drive;
|
|
||||||
|
|
||||||
int flags;
|
int flags;
|
||||||
int interrupt;
|
int interrupt;
|
||||||
|
|
||||||
int irq; /* Should be 6 by default. */
|
int irq; /* Should be 6 by default. */
|
||||||
int dma_ch; /* Should be 2 by default. */
|
int dma_ch; /* Should be 2 by default. */
|
||||||
|
|
||||||
int bit_rate; /* Should be 250 at start. */
|
int drvrate[4];
|
||||||
int paramstogo;
|
|
||||||
|
|
||||||
sector_id_t read_track_sector;
|
sector_id_t read_track_sector;
|
||||||
sector_id_t format_sector_id;
|
sector_id_t format_sector_id;
|
||||||
@@ -183,6 +192,7 @@ extern int fdc_get_compare_condition(fdc_t *fdc);
|
|||||||
extern int fdc_is_deleted(fdc_t *fdc);
|
extern int fdc_is_deleted(fdc_t *fdc);
|
||||||
extern int fdc_is_sk(fdc_t *fdc);
|
extern int fdc_is_sk(fdc_t *fdc);
|
||||||
extern void fdc_set_wrong_am(fdc_t *fdc);
|
extern void fdc_set_wrong_am(fdc_t *fdc);
|
||||||
|
extern void fdc_set_power_down(fdc_t *fdc, uint8_t power_down);
|
||||||
extern int fdc_get_drive(fdc_t *fdc);
|
extern int fdc_get_drive(fdc_t *fdc);
|
||||||
extern int fdc_get_perp(fdc_t *fdc);
|
extern int fdc_get_perp(fdc_t *fdc);
|
||||||
extern int fdc_get_format_n(fdc_t *fdc);
|
extern int fdc_get_format_n(fdc_t *fdc);
|
||||||
|
|||||||
@@ -1127,7 +1127,7 @@ machine_at_ms5146_init(const machine_t *model)
|
|||||||
pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3);
|
pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3);
|
||||||
|
|
||||||
device_add(&sis_5571_device);
|
device_add(&sis_5571_device);
|
||||||
device_add(&keyboard_ps2_ali_pci_device);
|
device_add(&keyboard_ps2_ami_pci_device);
|
||||||
device_add(&w83877f_device);
|
device_add(&w83877f_device);
|
||||||
device_add(&sst_flash_29ee010_device);
|
device_add(&sst_flash_29ee010_device);
|
||||||
|
|
||||||
@@ -1151,13 +1151,13 @@ machine_at_cb52x_si_init(const machine_t *model)
|
|||||||
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
|
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
|
||||||
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4);
|
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4);
|
||||||
pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4);
|
pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4);
|
||||||
pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1);
|
pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1);
|
||||||
pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2);
|
pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2);
|
||||||
pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3);
|
pci_register_slot(0x07, PCI_CARD_NORMAL, 4, 1, 2, 3);
|
||||||
|
|
||||||
device_add(&sis_5571_device);
|
device_add(&sis_5571_device);
|
||||||
device_add(&keyboard_ps2_ali_pci_device);
|
device_add(&keyboard_ps2_ami_pci_device);
|
||||||
device_add(&fdc37c669_device);
|
device_add(&fdc37c669_370_device);
|
||||||
device_add(&sst_flash_29ee010_device);
|
device_add(&sst_flash_29ee010_device);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -12,13 +12,15 @@
|
|||||||
*
|
*
|
||||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||||
*
|
*
|
||||||
* Copyright 2016-2018 Miran Grca.
|
* Copyright 2016-2024 Miran Grca.
|
||||||
*/
|
*/
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
#define HAVE_STDARG_H
|
||||||
#include <86box/86box.h>
|
#include <86box/86box.h>
|
||||||
#include <86box/io.h>
|
#include <86box/io.h>
|
||||||
#include <86box/timer.h>
|
#include <86box/timer.h>
|
||||||
@@ -45,35 +47,67 @@ typedef struct fdc37c669_t {
|
|||||||
|
|
||||||
static int next_id = 0;
|
static int next_id = 0;
|
||||||
|
|
||||||
static uint16_t
|
#ifdef ENABLE_FDC37C669_LOG
|
||||||
make_port(fdc37c669_t *dev, uint8_t reg)
|
int fdc37c669_do_log = ENABLE_FDC37C669_LOG;
|
||||||
|
|
||||||
|
static void
|
||||||
|
fdc37c669_log(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
uint16_t p = 0;
|
va_list ap;
|
||||||
uint16_t mask = 0;
|
|
||||||
|
|
||||||
switch (reg) {
|
if (fdc37c669_do_log) {
|
||||||
case 0x20:
|
va_start(ap, fmt);
|
||||||
case 0x21:
|
pclog_ex(fmt, ap);
|
||||||
case 0x22:
|
va_end(ap);
|
||||||
mask = 0xfc;
|
|
||||||
break;
|
|
||||||
case 0x23:
|
|
||||||
mask = 0xff;
|
|
||||||
break;
|
|
||||||
case 0x24:
|
|
||||||
case 0x25:
|
|
||||||
mask = 0xfe;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define fdc37c669_log(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
p = ((uint16_t) (dev->regs[reg] & mask)) << 2;
|
static void
|
||||||
if (reg == 0x22)
|
fdc37c669_fdc_handler(fdc37c669_t *dev)
|
||||||
p |= 6;
|
{
|
||||||
|
fdc_remove(dev->fdc);
|
||||||
|
if (dev->regs[0x20] & 0xc0)
|
||||||
|
fdc_set_base(dev->fdc, ((uint16_t) dev->regs[0x20]) << 2);
|
||||||
|
}
|
||||||
|
|
||||||
return p;
|
static void
|
||||||
|
fdc37c669_uart_handler(fdc37c669_t *dev, uint8_t uart)
|
||||||
|
{
|
||||||
|
uint8_t uart_reg = 0x24 + uart;
|
||||||
|
uint8_t pwrdn_mask = 0x08 << (uart << 2);
|
||||||
|
uint8_t uart_shift = ((uart ^ 1) << 2);
|
||||||
|
|
||||||
|
serial_remove(dev->uart[uart]);
|
||||||
|
if ((dev->regs[0x02] & pwrdn_mask) && (dev->regs[uart_reg] & 0xc0))
|
||||||
|
serial_setup(dev->uart[0], ((uint16_t) dev->regs[0x24]) << 2,
|
||||||
|
(dev->regs[0x28] >> uart_shift) & 0x0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double
|
||||||
|
fdc37c669_uart_get_clock_src(fdc37c669_t *dev, uint8_t uart)
|
||||||
|
{
|
||||||
|
double clock_srcs[4] = { 24000000.0 / 13.0, 24000000.0 / 12.0, 24000000.0 / 3.0, 24000000.0 / 3.0 };
|
||||||
|
double ret;
|
||||||
|
uint8_t clock_src_0 = !!(dev->regs[0x04] & (0x10 << uart));
|
||||||
|
uint8_t clock_src_1 = !!(dev->regs[0x0c] & (0x40 << uart));
|
||||||
|
uint8_t clock_src = clock_src_0 | (clock_src_1 << 1);
|
||||||
|
|
||||||
|
ret = clock_srcs[clock_src];
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fdc37c669_lpt_handler(fdc37c669_t *dev)
|
||||||
|
{
|
||||||
|
uint8_t mask = ~(dev->regs[0x04] & 0x01);
|
||||||
|
|
||||||
|
lpt_port_remove(dev->id);
|
||||||
|
if ((dev->regs[0x01] & 0x04) && (dev->regs[0x23] >= 0x40))
|
||||||
|
lpt_port_init(dev->id, ((uint16_t) (dev->regs[0x23] & mask)) << 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -81,149 +115,153 @@ fdc37c669_write(uint16_t port, uint8_t val, void *priv)
|
|||||||
{
|
{
|
||||||
fdc37c669_t *dev = (fdc37c669_t *) priv;
|
fdc37c669_t *dev = (fdc37c669_t *) priv;
|
||||||
uint8_t index = (port & 1) ? 0 : 1;
|
uint8_t index = (port & 1) ? 0 : 1;
|
||||||
uint8_t valxor = 0;
|
uint8_t valxor = val ^ dev->regs[dev->cur_reg];
|
||||||
uint8_t max = 42;
|
|
||||||
|
fdc37c669_log("[%04X:%08X] [W] %04X = %02X (%i, %i)\n", CS, cpu_state.pc, port, val,
|
||||||
|
dev->tries, dev->locked);
|
||||||
|
|
||||||
if (index) {
|
if (index) {
|
||||||
if ((val == 0x55) && !dev->locked) {
|
if ((val == 0x55) && !dev->locked) {
|
||||||
if (dev->tries) {
|
dev->tries = (dev->tries + 1) & 1;
|
||||||
|
|
||||||
|
if (!dev->tries)
|
||||||
dev->locked = 1;
|
dev->locked = 1;
|
||||||
dev->tries = 0;
|
|
||||||
} else
|
|
||||||
dev->tries++;
|
|
||||||
} else {
|
} else {
|
||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if (val < max)
|
|
||||||
dev->cur_reg = val;
|
|
||||||
if (val == 0xaa)
|
if (val == 0xaa)
|
||||||
dev->locked = 0;
|
dev->locked = 0;
|
||||||
} else {
|
else
|
||||||
if (dev->tries)
|
dev->cur_reg = val;
|
||||||
dev->tries = 0;
|
} else
|
||||||
}
|
dev->tries = 0;
|
||||||
}
|
}
|
||||||
return;
|
} else if (!dev->rw_locked || (dev->cur_reg > 0x0f)) switch (dev->cur_reg) {
|
||||||
} else {
|
case 0x00:
|
||||||
if (dev->locked) {
|
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x74) | (val & 0x8b);
|
||||||
if ((dev->cur_reg < 0x18) && (dev->rw_locked))
|
if (!dev->id && (valxor & 8))
|
||||||
return;
|
fdc_set_power_down(dev->fdc, !(val & 0x08));
|
||||||
if ((dev->cur_reg >= 0x26) && (dev->cur_reg <= 0x27))
|
break;
|
||||||
return;
|
case 0x01:
|
||||||
if (dev->cur_reg == 0x29)
|
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x73) | (val & 0x8c);
|
||||||
return;
|
if (valxor & 0x04)
|
||||||
valxor = val ^ dev->regs[dev->cur_reg];
|
fdc37c669_lpt_handler(dev);
|
||||||
|
if (valxor & 0x80)
|
||||||
|
dev->rw_locked = !(val & 0x80);
|
||||||
|
break;
|
||||||
|
case 0x02:
|
||||||
|
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x77) | (val & 0x88);
|
||||||
|
if (valxor & 0x08)
|
||||||
|
fdc37c669_uart_handler(dev, 0);
|
||||||
|
if (valxor & 0x80)
|
||||||
|
fdc37c669_uart_handler(dev, 1);
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x08) | (val & 0xf7);
|
||||||
|
if (!dev->id && (valxor & 0x02))
|
||||||
|
fdc_update_enh_mode(dev->fdc, !!(val & 0x02));
|
||||||
|
break;
|
||||||
|
case 0x04:
|
||||||
dev->regs[dev->cur_reg] = val;
|
dev->regs[dev->cur_reg] = val;
|
||||||
} else
|
if (valxor & 0x03)
|
||||||
return;
|
fdc37c669_lpt_handler(dev);
|
||||||
}
|
if (valxor & 0x10)
|
||||||
|
serial_set_clock_src(dev->uart[0], fdc37c669_uart_get_clock_src(dev, 0));
|
||||||
switch (dev->cur_reg) {
|
if (valxor & 0x20)
|
||||||
case 0:
|
serial_set_clock_src(dev->uart[1], fdc37c669_uart_get_clock_src(dev, 1));
|
||||||
if (!dev->id && (valxor & 8)) {
|
|
||||||
fdc_remove(dev->fdc);
|
|
||||||
if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0))
|
|
||||||
fdc_set_base(dev->fdc, make_port(dev, 0x20));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 0x05:
|
||||||
if (valxor & 4) {
|
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x83) | (val & 0x7c);
|
||||||
if (dev->id) {
|
|
||||||
lpt2_remove();
|
|
||||||
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
|
|
||||||
lpt2_init(make_port(dev, 0x23));
|
|
||||||
} else {
|
|
||||||
lpt1_remove();
|
|
||||||
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
|
|
||||||
lpt1_init(make_port(dev, 0x23));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (valxor & 7)
|
|
||||||
dev->rw_locked = (val & 8) ? 0 : 1;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
if (valxor & 8) {
|
|
||||||
serial_remove(dev->uart[0]);
|
|
||||||
if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40))
|
|
||||||
serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4);
|
|
||||||
}
|
|
||||||
if (valxor & 0x80) {
|
|
||||||
serial_remove(dev->uart[1]);
|
|
||||||
if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40))
|
|
||||||
serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
if (!dev->id && (valxor & 2))
|
|
||||||
fdc_update_enh_mode(dev->fdc, (val & 2) ? 1 : 0);
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
if (!dev->id && (valxor & 0x18))
|
if (!dev->id && (valxor & 0x18))
|
||||||
fdc_update_densel_force(dev->fdc, (val & 0x18) >> 3);
|
fdc_update_densel_force(dev->fdc, (val & 0x18) >> 3);
|
||||||
if (!dev->id && (valxor & 0x20))
|
if (!dev->id && (valxor & 0x20))
|
||||||
fdc_set_swap(dev->fdc, (val & 0x20) >> 5);
|
fdc_set_swap(dev->fdc, (val & 0x20) >> 5);
|
||||||
break;
|
break;
|
||||||
case 0xB:
|
case 0x06:
|
||||||
if (!dev->id && (valxor & 3))
|
dev->regs[dev->cur_reg] = val;
|
||||||
fdc_update_rwc(dev->fdc, 0, val & 3);
|
break;
|
||||||
if (!dev->id && (valxor & 0xC))
|
case 0x07:
|
||||||
fdc_update_rwc(dev->fdc, 1, (val & 0xC) >> 2);
|
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x06) | (val & 0xf9);
|
||||||
|
break;
|
||||||
|
case 0x08:
|
||||||
|
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x0f) | (val & 0xf0);
|
||||||
|
break;
|
||||||
|
case 0x09:
|
||||||
|
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x38) | (val & 0xc7);
|
||||||
|
break;
|
||||||
|
case 0x0a:
|
||||||
|
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0xf0) | (val & 0x0f);
|
||||||
|
break;
|
||||||
|
case 0x0b:
|
||||||
|
dev->regs[dev->cur_reg] = val;
|
||||||
|
if (!dev->id && (valxor & 0x03))
|
||||||
|
fdc_update_rwc(dev->fdc, 0, val & 0x03);
|
||||||
|
if (!dev->id && (valxor & 0x0c))
|
||||||
|
fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2);
|
||||||
|
break;
|
||||||
|
case 0x0c:
|
||||||
|
dev->regs[dev->cur_reg] = val;
|
||||||
|
if (valxor & 0x40)
|
||||||
|
serial_set_clock_src(dev->uart[0], fdc37c669_uart_get_clock_src(dev, 0));
|
||||||
|
if (valxor & 0x80)
|
||||||
|
serial_set_clock_src(dev->uart[1], fdc37c669_uart_get_clock_src(dev, 1));
|
||||||
|
break;
|
||||||
|
case 0x0f:
|
||||||
|
case 0x12 ... 0x1f:
|
||||||
|
dev->regs[dev->cur_reg] = val;
|
||||||
|
break;
|
||||||
|
case 0x10:
|
||||||
|
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x07) | (val & 0xf8);
|
||||||
|
break;
|
||||||
|
case 0x11:
|
||||||
|
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0xfc) | (val & 0x03);
|
||||||
break;
|
break;
|
||||||
case 0x20:
|
case 0x20:
|
||||||
if (!dev->id && (valxor & 0xfc)) {
|
dev->regs[dev->cur_reg] = val & 0xfc;
|
||||||
fdc_remove(dev->fdc);
|
if (!dev->id && (valxor & 0xfc))
|
||||||
if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0))
|
fdc37c669_fdc_handler(dev);
|
||||||
fdc_set_base(dev->fdc, make_port(dev, 0x20));
|
break;
|
||||||
}
|
case 0x21:
|
||||||
|
dev->regs[dev->cur_reg] = val & 0xfc;
|
||||||
|
break;
|
||||||
|
case 0x22:
|
||||||
|
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x03) | (val & 0xfc);
|
||||||
break;
|
break;
|
||||||
case 0x23:
|
case 0x23:
|
||||||
if (valxor) {
|
dev->regs[dev->cur_reg] = val;
|
||||||
if (dev->id) {
|
if (valxor)
|
||||||
lpt2_remove();
|
fdc37c669_lpt_handler(dev);
|
||||||
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
|
|
||||||
lpt2_init(make_port(dev, 0x23));
|
|
||||||
} else {
|
|
||||||
lpt1_remove();
|
|
||||||
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
|
|
||||||
lpt1_init(make_port(dev, 0x23));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 0x24:
|
case 0x24:
|
||||||
if (valxor & 0xfe) {
|
dev->regs[dev->cur_reg] = val & 0xfe;
|
||||||
serial_remove(dev->uart[0]);
|
if (valxor & 0xfe)
|
||||||
if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40))
|
fdc37c669_uart_handler(dev, 0);
|
||||||
serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 0x25:
|
case 0x25:
|
||||||
if (valxor & 0xfe) {
|
dev->regs[dev->cur_reg] = val & 0xfe;
|
||||||
serial_remove(dev->uart[1]);
|
if (valxor & 0xfe)
|
||||||
if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40))
|
fdc37c669_uart_handler(dev, 1);
|
||||||
serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f);
|
break;
|
||||||
}
|
case 0x26:
|
||||||
|
dev->regs[dev->cur_reg] = val;
|
||||||
|
if (valxor & 0xf0)
|
||||||
|
fdc_set_dma_ch(dev->fdc, val >> 4);
|
||||||
break;
|
break;
|
||||||
case 0x27:
|
case 0x27:
|
||||||
if (valxor & 0xf) {
|
dev->regs[dev->cur_reg] = val;
|
||||||
if (dev->id)
|
if (valxor & 0xf0)
|
||||||
lpt2_irq(val & 0xf);
|
fdc_set_irq(dev->fdc, val >> 4);
|
||||||
else
|
if (valxor & 0x0f)
|
||||||
lpt1_irq(val & 0xf);
|
lpt_port_irq(dev->id, val & 0x0f);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 0x28:
|
case 0x28:
|
||||||
if (valxor & 0xf) {
|
dev->regs[dev->cur_reg] = val;
|
||||||
serial_remove(dev->uart[1]);
|
if (valxor & 0xf0)
|
||||||
if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40))
|
fdc37c669_uart_handler(dev, 0);
|
||||||
serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f);
|
if (valxor & 0x0f)
|
||||||
}
|
fdc37c669_uart_handler(dev, 1);
|
||||||
if (valxor & 0xf0) {
|
|
||||||
serial_remove(dev->uart[0]);
|
|
||||||
if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40))
|
|
||||||
serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
case 0x29:
|
||||||
default:
|
dev->regs[dev->cur_reg] = val & 0x0f;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,23 +276,23 @@ fdc37c669_read(uint16_t port, void *priv)
|
|||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if (index)
|
if (index)
|
||||||
ret = dev->cur_reg;
|
ret = dev->cur_reg;
|
||||||
else if ((dev->cur_reg >= 0x18) || !dev->rw_locked)
|
else if (!dev->rw_locked || (dev->cur_reg > 0x0f))
|
||||||
ret = dev->regs[dev->cur_reg];
|
ret = dev->regs[dev->cur_reg];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fdc37c669_log("[%04X:%08X] [R] %04X = %02X (%i, %i)\n", CS, cpu_state.pc, port, ret,
|
||||||
|
dev->tries, dev->locked);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c669_reset(fdc37c669_t *dev)
|
fdc37c669_reset(void *priv)
|
||||||
{
|
{
|
||||||
serial_remove(dev->uart[0]);
|
fdc37c669_t *dev = (fdc37c669_t *) priv;
|
||||||
serial_setup(dev->uart[0], COM1_ADDR, COM1_IRQ);
|
|
||||||
|
|
||||||
serial_remove(dev->uart[1]);
|
memset(dev->regs, 0x00, 42);
|
||||||
serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ);
|
|
||||||
|
|
||||||
memset(dev->regs, 0, 42);
|
|
||||||
dev->regs[0x00] = 0x28;
|
dev->regs[0x00] = 0x28;
|
||||||
dev->regs[0x01] = 0x9c;
|
dev->regs[0x01] = 0x9c;
|
||||||
dev->regs[0x02] = 0x88;
|
dev->regs[0x02] = 0x88;
|
||||||
@@ -262,32 +300,23 @@ fdc37c669_reset(fdc37c669_t *dev)
|
|||||||
dev->regs[0x06] = 0xff;
|
dev->regs[0x06] = 0xff;
|
||||||
dev->regs[0x0d] = 0x03;
|
dev->regs[0x0d] = 0x03;
|
||||||
dev->regs[0x0e] = 0x02;
|
dev->regs[0x0e] = 0x02;
|
||||||
dev->regs[0x1e] = 0x80; /* Gameport controller. */
|
dev->regs[0x1e] = 0x3c; /* Gameport controller. */
|
||||||
dev->regs[0x20] = (FDC_PRIMARY_ADDR >> 2) & 0xfc;
|
dev->regs[0x20] = 0x3c;
|
||||||
dev->regs[0x21] = (0x1f0 >> 2) & 0xfc;
|
dev->regs[0x21] = 0x3c;
|
||||||
dev->regs[0x22] = ((0x3f6 >> 2) & 0xfc) | 1;
|
dev->regs[0x22] = 0x3d;
|
||||||
|
|
||||||
if (dev->id == 1) {
|
if (dev->id == 1) {
|
||||||
dev->regs[0x23] = (LPT2_ADDR >> 2);
|
|
||||||
|
|
||||||
lpt2_remove();
|
|
||||||
lpt2_init(LPT2_ADDR);
|
|
||||||
|
|
||||||
dev->regs[0x24] = (COM3_ADDR >> 2) & 0xfe;
|
|
||||||
dev->regs[0x25] = (COM4_ADDR >> 2) & 0xfe;
|
|
||||||
} else {
|
|
||||||
fdc_reset(dev->fdc);
|
fdc_reset(dev->fdc);
|
||||||
|
fdc37c669_fdc_handler(dev);
|
||||||
lpt1_remove();
|
|
||||||
lpt1_init(LPT1_ADDR);
|
|
||||||
|
|
||||||
dev->regs[0x23] = (LPT1_ADDR >> 2);
|
|
||||||
|
|
||||||
dev->regs[0x24] = (COM1_ADDR >> 2) & 0xfe;
|
|
||||||
dev->regs[0x25] = (COM2_ADDR >> 2) & 0xfe;
|
|
||||||
}
|
}
|
||||||
dev->regs[0x26] = (2 << 4) | 3;
|
|
||||||
dev->regs[0x27] = (6 << 4) | (dev->id ? 5 : 7);
|
fdc37c669_uart_handler(dev, 0);
|
||||||
dev->regs[0x28] = (4 << 4) | 3;
|
serial_set_clock_src(dev->uart[0], fdc37c669_uart_get_clock_src(dev, 0));
|
||||||
|
|
||||||
|
fdc37c669_uart_handler(dev, 1);
|
||||||
|
serial_set_clock_src(dev->uart[1], fdc37c669_uart_get_clock_src(dev, 1));
|
||||||
|
|
||||||
|
fdc37c669_lpt_handler(dev);
|
||||||
|
|
||||||
dev->locked = 0;
|
dev->locked = 0;
|
||||||
dev->rw_locked = 0;
|
dev->rw_locked = 0;
|
||||||
@@ -317,8 +346,8 @@ fdc37c669_init(const device_t *info)
|
|||||||
dev->uart[0] = device_add_inst(&ns16550_device, (next_id << 1) + 1);
|
dev->uart[0] = device_add_inst(&ns16550_device, (next_id << 1) + 1);
|
||||||
dev->uart[1] = device_add_inst(&ns16550_device, (next_id << 1) + 2);
|
dev->uart[1] = device_add_inst(&ns16550_device, (next_id << 1) + 2);
|
||||||
|
|
||||||
io_sethandler(info->local ? FDC_SECONDARY_ADDR : (next_id ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR), 0x0002,
|
io_sethandler(info->local ? FDC_SECONDARY_ADDR : (next_id ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR),
|
||||||
fdc37c669_read, NULL, NULL, fdc37c669_write, NULL, NULL, dev);
|
0x0002, fdc37c669_read, NULL, NULL, fdc37c669_write, NULL, NULL, dev);
|
||||||
|
|
||||||
fdc37c669_reset(dev);
|
fdc37c669_reset(dev);
|
||||||
|
|
||||||
@@ -334,7 +363,7 @@ const device_t fdc37c669_device = {
|
|||||||
.local = 0,
|
.local = 0,
|
||||||
.init = fdc37c669_init,
|
.init = fdc37c669_init,
|
||||||
.close = fdc37c669_close,
|
.close = fdc37c669_close,
|
||||||
.reset = NULL,
|
.reset = fdc37c669_reset,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
@@ -348,7 +377,7 @@ const device_t fdc37c669_370_device = {
|
|||||||
.local = 1,
|
.local = 1,
|
||||||
.init = fdc37c669_init,
|
.init = fdc37c669_init,
|
||||||
.close = fdc37c669_close,
|
.close = fdc37c669_close,
|
||||||
.reset = NULL,
|
.reset = fdc37c669_reset,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
|
|||||||
Reference in New Issue
Block a user