diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 88948aed9..f30d86168 100644 --- a/src/floppy/fdc.c +++ b/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 = { diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 08e57c09b..fa1c070f1 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -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) { dev->calc_crc.word = 0xFFFF; fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc)); - find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; - find->sync_pos = 0xFFFFFFFF; - dev->preceding_bit[side] = dev->last_word[side] & 1; + find->sync_marks = find->bits_obtained = + find->bytes_obtained = 0; + find->sync_pos = 0xFFFFFFFF; + dev->preceding_bit[side] = dev->last_word[side] & 1; dev->state++; return; } 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->error_condition = 0; - dev->state = STATE_IDLE; - fdc_finishread(d86f_fdc); + dev->data_find.sync_marks = dev->data_find.bits_obtained = + dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + dev->state = STATE_IDLE; fdc_nodataam(d86f_fdc); 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 (!(dev->last_word[side] & 1)) { - find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; - find->sync_pos = 0xFFFFFFFF; + find->sync_marks = find->bits_obtained = + 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)) { - dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; - dev->error_condition = 0; - dev->state = STATE_IDLE; - fdc_finishread(d86f_fdc); + dev->data_find.sync_marks = dev->data_find.bits_obtained = + dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + dev->state = STATE_IDLE; fdc_nodataam(d86f_fdc); return; } @@ -1433,22 +1435,26 @@ d86f_read_sector_id(int drive, int side, int match) if (!(dev->id_find.bits_obtained & 15)) { /* We've got a byte. */ 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)); } 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++; if (dev->id_find.bytes_obtained == 6) { /* We've got the ID. */ - if ((dev->calc_crc.word != dev->track_crc.word) && (dev->last_sector.dword == dev->req_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->calc_crc.word != dev->track_crc.word) && + (dev->last_sector.dword == dev->req_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)) { dev->error_condition = 0; dev->state = STATE_IDLE; - fdc_finishread(d86f_fdc); fdc_headercrcerror(d86f_fdc); } else if (dev->state == STATE_0A_READ_ID) 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)) { /* 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; - 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.sync_marks = dev->id_find.bits_obtained = + 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; } else { /* 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; 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) { /* 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. */ - 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)) { - dev->error_condition |= 4; /* Mark that the sector ID is not the one expected by the FDC. */ + /* Code corrected: Only the C, H, and N portions of the + sector ID are compared, the R portion + (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. */ 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++; } 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); else { #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); else #endif @@ -1589,7 +1608,9 @@ d86f_read_sector_data(int drive, int side) } else { if (dev->data_find.bytes_obtained < d86f_get_data_len(drive)) { 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) dev->dma_over++; } @@ -1597,17 +1618,19 @@ d86f_read_sector_data(int drive, int side) } fdd_calccrc(data, &(dev->calc_crc)); } 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++; if (dev->data_find.bytes_obtained == (crc_pos + fdc_get_gap(d86f_fdc))) { /* We've got the 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); - dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; - dev->error_condition = 0; - dev->state = STATE_IDLE; - fdc_finishread(d86f_fdc); + d86f_log("86F: Data CRC error: %04X != %04X (%08X)\n", dev->track_crc.word, + dev->calc_crc.word, dev->last_sector.dword); + dev->data_find.sync_marks = dev->data_find.bits_obtained = + dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + dev->state = STATE_IDLE; fdc_datacrcerror(d86f_fdc); } 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; @@ -2146,7 +2169,8 @@ d86f_turbo_read(int drive, int side) } else { if (dev->turbo_pos < (128UL << dev->req_sector.id.n)) { 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) dev->dma_over++; } @@ -2163,7 +2187,6 @@ d86f_turbo_read(int drive, int side) #endif dev->error_condition = 0; dev->state = STATE_IDLE; - fdc_finishread(d86f_fdc); fdc_datacrcerror(d86f_fdc); } else if ((flags & SECTOR_CRC_ERROR) && (dev->state == STATE_02_READ_DATA)) { #ifdef ENABLE_D86F_LOG diff --git a/src/include/86box/fdc.h b/src/include/86box/fdc.h index 9441bdfc4..09c9c4578 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -65,76 +65,85 @@ typedef struct fdc_t { uint8_t st0; uint8_t swap; uint8_t dtl; + uint8_t swwp; uint8_t disable_write; uint8_t st5; uint8_t st6; uint8_t error; - uint8_t params[8]; - uint8_t res[11]; - uint8_t specify[2]; uint8_t config; 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]; + uint16_t pcn[4]; + uint16_t base_address; + uint16_t rw_track; - int head; - 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 bit_rate; /* Should be 250 at start. */ - int data_ready; - int inread; int bitcell_period; - int enh_mode; - int rwc[4]; - int drvrate[4]; 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 mfm; - int deleted; - int wrong_am; - int sc; int satisfying_sectors; - int fintr; - int rw_drive; int flags; int interrupt; - int irq; /* Should be 6 by default. */ - int dma_ch; /* Should be 2 by default. */ + int irq; /* Should be 6 by default. */ + int dma_ch; /* Should be 2 by default. */ - int bit_rate; /* Should be 250 at start. */ - int paramstogo; + int drvrate[4]; sector_id_t read_track_sector; 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_sk(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_perp(fdc_t *fdc); extern int fdc_get_format_n(fdc_t *fdc); diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index 01459f144..a3e777dbd 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -1127,7 +1127,7 @@ machine_at_ms5146_init(const machine_t *model) pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); 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(&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(0x01, PCI_CARD_SOUTHBRIDGE, 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(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(&keyboard_ps2_ali_pci_device); - device_add(&fdc37c669_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c669_370_device); device_add(&sst_flash_29ee010_device); return ret; diff --git a/src/sio/sio_fdc37c669.c b/src/sio/sio_fdc37c669.c index b2c8933c6..cb678427c 100644 --- a/src/sio/sio_fdc37c669.c +++ b/src/sio/sio_fdc37c669.c @@ -12,13 +12,15 @@ * * Authors: Miran Grca, * - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2024 Miran Grca. */ +#include #include #include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/io.h> #include <86box/timer.h> @@ -45,35 +47,67 @@ typedef struct fdc37c669_t { static int next_id = 0; -static uint16_t -make_port(fdc37c669_t *dev, uint8_t reg) +#ifdef ENABLE_FDC37C669_LOG +int fdc37c669_do_log = ENABLE_FDC37C669_LOG; + +static void +fdc37c669_log(const char *fmt, ...) { - uint16_t p = 0; - uint16_t mask = 0; + va_list ap; - switch (reg) { - case 0x20: - case 0x21: - case 0x22: - mask = 0xfc; - break; - case 0x23: - mask = 0xff; - break; - case 0x24: - case 0x25: - mask = 0xfe; - break; - - default: - break; + if (fdc37c669_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } +} +#else +# define fdc37c669_log(fmt, ...) +#endif - p = ((uint16_t) (dev->regs[reg] & mask)) << 2; - if (reg == 0x22) - p |= 6; +static void +fdc37c669_fdc_handler(fdc37c669_t *dev) +{ + 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 @@ -81,149 +115,153 @@ fdc37c669_write(uint16_t port, uint8_t val, void *priv) { fdc37c669_t *dev = (fdc37c669_t *) priv; uint8_t index = (port & 1) ? 0 : 1; - uint8_t valxor = 0; - uint8_t max = 42; + uint8_t valxor = val ^ dev->regs[dev->cur_reg]; + + fdc37c669_log("[%04X:%08X] [W] %04X = %02X (%i, %i)\n", CS, cpu_state.pc, port, val, + dev->tries, dev->locked); if (index) { if ((val == 0x55) && !dev->locked) { - if (dev->tries) { + dev->tries = (dev->tries + 1) & 1; + + if (!dev->tries) dev->locked = 1; - dev->tries = 0; - } else - dev->tries++; } else { if (dev->locked) { - if (val < max) - dev->cur_reg = val; if (val == 0xaa) dev->locked = 0; - } else { - if (dev->tries) - dev->tries = 0; - } + else + dev->cur_reg = val; + } else + dev->tries = 0; } - return; - } else { - if (dev->locked) { - if ((dev->cur_reg < 0x18) && (dev->rw_locked)) - return; - if ((dev->cur_reg >= 0x26) && (dev->cur_reg <= 0x27)) - return; - if (dev->cur_reg == 0x29) - return; - valxor = val ^ dev->regs[dev->cur_reg]; + } else if (!dev->rw_locked || (dev->cur_reg > 0x0f)) switch (dev->cur_reg) { + case 0x00: + dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x74) | (val & 0x8b); + if (!dev->id && (valxor & 8)) + fdc_set_power_down(dev->fdc, !(val & 0x08)); + break; + case 0x01: + dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x73) | (val & 0x8c); + if (valxor & 0x04) + 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; - } else - return; - } - - switch (dev->cur_reg) { - case 0: - 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)); - } + if (valxor & 0x03) + fdc37c669_lpt_handler(dev); + if (valxor & 0x10) + serial_set_clock_src(dev->uart[0], fdc37c669_uart_get_clock_src(dev, 0)); + if (valxor & 0x20) + serial_set_clock_src(dev->uart[1], fdc37c669_uart_get_clock_src(dev, 1)); break; - case 1: - if (valxor & 4) { - 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: + case 0x05: + dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x83) | (val & 0x7c); if (!dev->id && (valxor & 0x18)) fdc_update_densel_force(dev->fdc, (val & 0x18) >> 3); if (!dev->id && (valxor & 0x20)) fdc_set_swap(dev->fdc, (val & 0x20) >> 5); break; - case 0xB: - if (!dev->id && (valxor & 3)) - fdc_update_rwc(dev->fdc, 0, val & 3); - if (!dev->id && (valxor & 0xC)) - fdc_update_rwc(dev->fdc, 1, (val & 0xC) >> 2); + case 0x06: + dev->regs[dev->cur_reg] = val; + break; + case 0x07: + 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; case 0x20: - if (!dev->id && (valxor & 0xfc)) { - fdc_remove(dev->fdc); - if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0)) - fdc_set_base(dev->fdc, make_port(dev, 0x20)); - } + dev->regs[dev->cur_reg] = val & 0xfc; + if (!dev->id && (valxor & 0xfc)) + fdc37c669_fdc_handler(dev); + 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; case 0x23: - if (valxor) { - 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)); - } - } + dev->regs[dev->cur_reg] = val; + if (valxor) + fdc37c669_lpt_handler(dev); break; case 0x24: - if (valxor & 0xfe) { - 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); - } + dev->regs[dev->cur_reg] = val & 0xfe; + if (valxor & 0xfe) + fdc37c669_uart_handler(dev, 0); break; case 0x25: - if (valxor & 0xfe) { - 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); - } + dev->regs[dev->cur_reg] = val & 0xfe; + if (valxor & 0xfe) + fdc37c669_uart_handler(dev, 1); + break; + case 0x26: + dev->regs[dev->cur_reg] = val; + if (valxor & 0xf0) + fdc_set_dma_ch(dev->fdc, val >> 4); break; case 0x27: - if (valxor & 0xf) { - if (dev->id) - lpt2_irq(val & 0xf); - else - lpt1_irq(val & 0xf); - } + dev->regs[dev->cur_reg] = val; + if (valxor & 0xf0) + fdc_set_irq(dev->fdc, val >> 4); + if (valxor & 0x0f) + lpt_port_irq(dev->id, val & 0x0f); break; case 0x28: - if (valxor & 0xf) { - 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); - } - 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); - } + dev->regs[dev->cur_reg] = val; + if (valxor & 0xf0) + fdc37c669_uart_handler(dev, 0); + if (valxor & 0x0f) + fdc37c669_uart_handler(dev, 1); break; - - default: + case 0x29: + dev->regs[dev->cur_reg] = val & 0x0f; break; } } @@ -238,23 +276,23 @@ fdc37c669_read(uint16_t port, void *priv) if (dev->locked) { if (index) 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]; } + fdc37c669_log("[%04X:%08X] [R] %04X = %02X (%i, %i)\n", CS, cpu_state.pc, port, ret, + dev->tries, dev->locked); + return ret; } static void -fdc37c669_reset(fdc37c669_t *dev) +fdc37c669_reset(void *priv) { - serial_remove(dev->uart[0]); - serial_setup(dev->uart[0], COM1_ADDR, COM1_IRQ); + fdc37c669_t *dev = (fdc37c669_t *) priv; - serial_remove(dev->uart[1]); - serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ); + memset(dev->regs, 0x00, 42); - memset(dev->regs, 0, 42); dev->regs[0x00] = 0x28; dev->regs[0x01] = 0x9c; dev->regs[0x02] = 0x88; @@ -262,32 +300,23 @@ fdc37c669_reset(fdc37c669_t *dev) dev->regs[0x06] = 0xff; dev->regs[0x0d] = 0x03; dev->regs[0x0e] = 0x02; - dev->regs[0x1e] = 0x80; /* Gameport controller. */ - dev->regs[0x20] = (FDC_PRIMARY_ADDR >> 2) & 0xfc; - dev->regs[0x21] = (0x1f0 >> 2) & 0xfc; - dev->regs[0x22] = ((0x3f6 >> 2) & 0xfc) | 1; + dev->regs[0x1e] = 0x3c; /* Gameport controller. */ + dev->regs[0x20] = 0x3c; + dev->regs[0x21] = 0x3c; + dev->regs[0x22] = 0x3d; + 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); - - 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; + fdc37c669_fdc_handler(dev); } - dev->regs[0x26] = (2 << 4) | 3; - dev->regs[0x27] = (6 << 4) | (dev->id ? 5 : 7); - dev->regs[0x28] = (4 << 4) | 3; + + fdc37c669_uart_handler(dev, 0); + 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->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[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, - fdc37c669_read, NULL, NULL, fdc37c669_write, NULL, NULL, dev); + io_sethandler(info->local ? FDC_SECONDARY_ADDR : (next_id ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR), + 0x0002, fdc37c669_read, NULL, NULL, fdc37c669_write, NULL, NULL, dev); fdc37c669_reset(dev); @@ -334,7 +363,7 @@ const device_t fdc37c669_device = { .local = 0, .init = fdc37c669_init, .close = fdc37c669_close, - .reset = NULL, + .reset = fdc37c669_reset, { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, @@ -348,7 +377,7 @@ const device_t fdc37c669_370_device = { .local = 1, .init = fdc37c669_init, .close = fdc37c669_close, - .reset = NULL, + .reset = fdc37c669_reset, { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL,