1 // license:BSD-3-Clause 2 // copyright-holders:Olivier Galibert 3 #ifndef MAME_DEVICES_MACHINE_UPD765_H 4 #define MAME_DEVICES_MACHINE_UPD765_H 5 6 #pragma once 7 8 #include "fdc_pll.h" 9 10 class floppy_image_device; 11 12 /* 13 * ready = true if the ready line is physically connected to the floppy drive 14 * select = true if the fdc controls the floppy drive selection 15 * mode = mode_t::AT, mode_t::PS2 or mode_t::M30 for the fdcs that have reset-time selection 16 */ 17 18 class upd765_family_device : public device_t { 19 public: 20 enum class mode_t { AT, PS2, M30 }; 21 intrq_wr_callback()22 auto intrq_wr_callback() { return intrq_cb.bind(); } drq_wr_callback()23 auto drq_wr_callback() { return drq_cb.bind(); } hdl_wr_callback()24 auto hdl_wr_callback() { return hdl_cb.bind(); } us_wr_callback()25 auto us_wr_callback() { return us_cb.bind(); } idx_wr_callback()26 auto idx_wr_callback() { return idx_cb.bind(); } 27 28 virtual void map(address_map &map) = 0; 29 30 uint8_t dor_r(); 31 void dor_w(uint8_t data); 32 uint8_t tdr_r(); 33 void tdr_w(uint8_t data); 34 uint8_t msr_r(); 35 void dsr_w(uint8_t data); 36 uint8_t fifo_r(); 37 void fifo_w(uint8_t data); dir_r()38 uint8_t dir_r() { return do_dir_r(); } 39 void ccr_w(uint8_t data); 40 41 uint8_t do_dir_r(); 42 43 uint8_t dma_r(); 44 void dma_w(uint8_t data); 45 46 bool get_irq() const; 47 bool get_drq() const; 48 void tc_w(bool val); 49 void ready_w(bool val); 50 DECLARE_WRITE_LINE_MEMBER(tc_line_w)51 DECLARE_WRITE_LINE_MEMBER(tc_line_w) { tc_w(state == ASSERT_LINE); } 52 DECLARE_WRITE_LINE_MEMBER(reset_w); 53 54 void set_rate(int rate); // rate in bps, to be used when the fdc is externally frequency-controlled 55 56 void set_ready_line_connected(bool ready); 57 void set_select_lines_connected(bool select); 58 void set_floppy(floppy_image_device *image); 59 virtual void soft_reset(); 60 61 protected: 62 upd765_family_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); 63 64 virtual void device_resolve_objects() override; 65 virtual void device_start() override; 66 virtual void device_reset() override; 67 virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; 68 69 enum { 70 TIMER_DRIVE_READY_POLLING = 4 71 }; 72 73 enum { 74 PHASE_CMD, PHASE_EXEC, PHASE_RESULT 75 }; 76 77 enum { 78 MSR_DB = 0x0f, 79 MSR_CB = 0x10, 80 MSR_EXM = 0x20, 81 MSR_DIO = 0x40, 82 MSR_RQM = 0x80, 83 84 ST0_UNIT = 0x07, 85 ST0_NR = 0x08, 86 ST0_EC = 0x10, 87 ST0_SE = 0x20, 88 ST0_FAIL = 0x40, 89 ST0_UNK = 0x80, 90 ST0_ABRT = 0xc0, 91 92 ST1_MA = 0x01, 93 ST1_NW = 0x02, 94 ST1_ND = 0x04, 95 ST1_OR = 0x10, 96 ST1_DE = 0x20, 97 ST1_EN = 0x80, 98 99 ST2_MD = 0x01, 100 ST2_BC = 0x02, 101 ST2_SN = 0x04, 102 ST2_SH = 0x08, 103 ST2_WC = 0x10, 104 ST2_DD = 0x20, 105 ST2_CM = 0x40, 106 107 ST3_UNIT = 0x07, 108 ST3_TS = 0x08, 109 ST3_T0 = 0x10, 110 ST3_RY = 0x20, 111 ST3_WP = 0x40, 112 ST3_FT = 0x80, 113 114 FIF_THR = 0x0f, 115 FIF_POLL = 0x10, 116 FIF_DIS = 0x20, 117 FIF_EIS = 0x40, 118 119 SPEC_ND = 0x0001 120 }; 121 122 123 enum { 124 // General "doing nothing" state 125 IDLE, 126 127 // Main states 128 RECALIBRATE, 129 SEEK, 130 READ_DATA, 131 WRITE_DATA, 132 READ_TRACK, 133 FORMAT_TRACK, 134 READ_ID, 135 SCAN_DATA, 136 137 // Sub-states 138 COMMAND_DONE, 139 140 SEEK_MOVE, 141 SEEK_WAIT_STEP_SIGNAL_TIME, 142 SEEK_WAIT_STEP_SIGNAL_TIME_DONE, 143 SEEK_WAIT_STEP_TIME, 144 SEEK_WAIT_STEP_TIME_DONE, 145 SEEK_WAIT_DONE, 146 SEEK_DONE, 147 148 HEAD_LOAD, 149 HEAD_LOAD_DONE, 150 151 WAIT_INDEX, 152 WAIT_INDEX_DONE, 153 154 SCAN_ID, 155 SCAN_ID_FAILED, 156 157 SECTOR_READ, 158 SECTOR_WRITTEN, 159 TC_DONE, 160 161 TRACK_DONE, 162 163 // Live states 164 SEARCH_ADDRESS_MARK_HEADER, 165 READ_HEADER_BLOCK_HEADER, 166 READ_DATA_BLOCK_HEADER, 167 READ_ID_BLOCK, 168 SEARCH_ADDRESS_MARK_DATA, 169 SEARCH_ADDRESS_MARK_DATA_FAILED, 170 READ_SECTOR_DATA, 171 READ_SECTOR_DATA_BYTE, 172 SCAN_SECTOR_DATA_BYTE, 173 174 WRITE_SECTOR_SKIP_GAP2, 175 WRITE_SECTOR_SKIP_GAP2_BYTE, 176 WRITE_SECTOR_DATA, 177 WRITE_SECTOR_DATA_BYTE, 178 179 WRITE_TRACK_PRE_SECTORS, 180 WRITE_TRACK_PRE_SECTORS_BYTE, 181 182 WRITE_TRACK_SECTOR, 183 WRITE_TRACK_SECTOR_BYTE, 184 185 WRITE_TRACK_POST_SECTORS, 186 WRITE_TRACK_POST_SECTORS_BYTE 187 }; 188 189 struct pll_t { 190 attotime ctime, period, min_period, max_period, period_adjust_base, phase_adjust; 191 192 attotime write_start_time; 193 attotime write_buffer[32]; 194 int write_position; 195 int freq_hist; 196 197 void set_clock(const attotime &period); 198 void reset(const attotime &when); 199 int get_next_bit(attotime &tm, floppy_image_device *floppy, const attotime &limit); 200 bool write_next_bit(bool bit, attotime &tm, floppy_image_device *floppy, const attotime &limit); 201 void start_writing(const attotime &tm); 202 void commit(floppy_image_device *floppy, const attotime &tm); 203 void stop_writing(floppy_image_device *floppy, const attotime &tm); 204 }; 205 206 struct floppy_info { 207 enum { IRQ_NONE, IRQ_POLLED, IRQ_SEEK, IRQ_DONE }; 208 emu_timer *tm; 209 floppy_image_device *dev; 210 int id; 211 int main_state, sub_state; 212 int dir, counter; 213 uint8_t pcn, st0; 214 bool st0_filled; 215 bool live, index, ready; 216 }; 217 218 struct live_info { 219 enum { PT_NONE, PT_CRC_1, PT_CRC_2 }; 220 221 attotime tm; 222 int state, next_state; 223 floppy_info *fi; 224 uint16_t shift_reg; 225 uint16_t crc; 226 int bit_counter, byte_counter, previous_type; 227 bool data_separator_phase, data_bit_context; 228 uint8_t data_reg; 229 uint8_t idbuf[6]; 230 fdc_pll_t pll; 231 }; 232 233 static constexpr int rates[4] = { 500000, 300000, 250000, 1000000 }; 234 235 bool ready_connected, ready_polled, select_connected, select_multiplexed, has_dor; 236 237 bool external_ready; 238 239 int recalibrate_steps; 240 241 mode_t mode; 242 int main_phase; 243 244 live_info cur_live, checkpoint_live; 245 devcb_write_line intrq_cb, drq_cb, hdl_cb, idx_cb; 246 devcb_write8 us_cb; 247 bool cur_irq, other_irq, data_irq, drq, internal_drq, tc, tc_done, locked, mfm, scan_done; 248 floppy_info flopi[4]; 249 250 int fifo_pos, fifo_expected, command_pos, result_pos, sectors_read; 251 bool fifo_write; 252 uint8_t dor, dsr, msr, fifo[16], command[16], result[16]; 253 uint8_t st1, st2, st3; 254 uint8_t fifocfg; 255 uint8_t precomp; 256 uint16_t spec; 257 int sector_size; 258 int cur_rate; 259 int selected_drive; 260 261 emu_timer *poll_timer; 262 263 std::string results() const; 264 std::string ttsn() const; 265 266 enum { 267 C_CONFIGURE, 268 C_DUMP_REG, 269 C_FORMAT_TRACK, 270 C_LOCK, 271 C_PERPENDICULAR, 272 C_READ_DATA, 273 C_READ_ID, 274 C_READ_TRACK, 275 C_RECALIBRATE, 276 C_SEEK, 277 C_SENSE_DRIVE_STATUS, 278 C_SENSE_INTERRUPT_STATUS, 279 C_SPECIFY, 280 C_WRITE_DATA, 281 C_SCAN_EQUAL, 282 C_SCAN_LOW, 283 C_SCAN_HIGH, 284 C_MOTOR_ONOFF, 285 C_VERSION, 286 287 C_INVALID, 288 C_INCOMPLETE 289 }; 290 291 void end_reset(); 292 293 void delay_cycles(emu_timer *tm, int cycles); 294 void check_irq(); 295 void fifo_expect(int size, bool write); 296 void fifo_push(uint8_t data, bool internal); 297 uint8_t fifo_pop(bool internal); 298 void set_drq(bool state); 299 bool get_ready(int fid); 300 void set_ds(int fid); 301 302 void enable_transfer(); 303 void disable_transfer(); 304 int calc_sector_size(uint8_t size); 305 306 void run_drive_ready_polling(); 307 308 virtual int check_command(); 309 virtual void start_command(int cmd); 310 virtual void execute_command(int cmd); 311 virtual void command_end(floppy_info &fi, bool data_completion); 312 virtual uint8_t get_st3(floppy_info &fi); 313 314 void recalibrate_start(floppy_info &fi); 315 void seek_start(floppy_info &fi); 316 void seek_continue(floppy_info &fi); 317 318 void read_data_start(floppy_info &fi); 319 void read_data_continue(floppy_info &fi); 320 321 void write_data_start(floppy_info &fi); 322 void write_data_continue(floppy_info &fi); 323 324 void read_track_start(floppy_info &fi); 325 void read_track_continue(floppy_info &fi); 326 327 void format_track_start(floppy_info &fi); 328 void format_track_continue(floppy_info &fi); 329 330 void read_id_start(floppy_info &fi); 331 void read_id_continue(floppy_info &fi); 332 333 void scan_start(floppy_info &fi); 334 335 void general_continue(floppy_info &fi); 336 virtual void index_callback(floppy_image_device *floppy, int state); 337 bool sector_matches() const; 338 339 void live_start(floppy_info &fi, int live_state); 340 void live_abort(); 341 void checkpoint(); 342 void rollback(); 343 void live_delay(int state); 344 void live_sync(); 345 void live_run(attotime limit = attotime::never); 346 void live_write_raw(uint16_t raw); 347 void live_write_fm(uint8_t fm); 348 void live_write_mfm(uint8_t mfm); 349 350 bool read_one_bit(const attotime &limit); 351 bool write_one_bit(const attotime &limit); 352 get_drive_busy()353 virtual u8 get_drive_busy() const { return 0; } clr_drive_busy()354 virtual void clr_drive_busy() { }; 355 }; 356 357 class upd765a_device : public upd765_family_device { 358 public: upd765a_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,bool ready,bool select)359 upd765a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, bool ready, bool select) 360 : upd765a_device(mconfig, tag, owner, clock) 361 { 362 set_ready_line_connected(ready); 363 set_select_lines_connected(select); 364 } 365 upd765a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 366 367 virtual void map(address_map &map) override; 368 }; 369 370 class upd765b_device : public upd765_family_device { 371 public: upd765b_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,bool ready,bool select)372 upd765b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, bool ready, bool select) 373 : upd765b_device(mconfig, tag, owner, clock) 374 { 375 set_ready_line_connected(ready); 376 set_select_lines_connected(select); 377 } 378 upd765b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 379 380 virtual void map(address_map &map) override; 381 }; 382 383 class i8272a_device : public upd765_family_device { 384 public: i8272a_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,bool ready)385 i8272a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, bool ready) 386 : i8272a_device(mconfig, tag, owner, clock) 387 { 388 set_ready_line_connected(ready); 389 } 390 i8272a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 391 392 virtual void map(address_map &map) override; 393 }; 394 395 class i82072_device : public upd765_family_device { 396 public: i82072_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,bool ready)397 i82072_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, bool ready) 398 : i82072_device(mconfig, tag, owner, clock) 399 { 400 set_ready_line_connected(ready); 401 } 402 i82072_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 403 404 virtual void map(address_map &map) override; 405 406 protected: 407 virtual void device_start() override; 408 409 enum motorcfg_mask 410 { 411 MON = 0x0f, // motor on delay 412 MOFF = 0x70, // motor off delay 413 HSDA = 0x80 // high speed disk adjust 414 }; 415 416 virtual void soft_reset() override; 417 virtual int check_command() override; 418 virtual void start_command(int cmd) override; 419 virtual void execute_command(int cmd) override; 420 virtual void command_end(floppy_info &fi, bool data_completion) override; 421 virtual void index_callback(floppy_image_device *floppy, int state) override; get_drive_busy()422 virtual u8 get_drive_busy() const override { return drive_busy; }; clr_drive_busy()423 virtual void clr_drive_busy() override { drive_busy = 0; }; 424 425 void motor_control(int fid, bool start_motor); 426 427 private: 428 u8 motorcfg; 429 u8 motor_off_counter; 430 u8 motor_on_counter; 431 u8 drive_busy; 432 int delayed_command; 433 }; 434 435 class ps2_fdc_device : public upd765_family_device { 436 public: 437 void set_mode(mode_t mode); 438 439 uint8_t sra_r(); 440 uint8_t srb_r(); 441 442 protected: 443 ps2_fdc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); 444 445 virtual void device_start() override; 446 virtual void device_reset() override; 447 virtual void soft_reset() override; 448 virtual int check_command() override; 449 virtual void execute_command(int cmd) override; 450 451 uint8_t perpmode; 452 }; 453 454 class smc37c78_device : public ps2_fdc_device { 455 public: 456 smc37c78_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 457 458 virtual void map(address_map &map) override; 459 }; 460 461 class upd72065_device : public upd765_family_device { 462 public: upd72065_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,bool ready,bool select)463 upd72065_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, bool ready, bool select) 464 : upd72065_device(mconfig, tag, owner, clock) 465 { 466 set_ready_line_connected(ready); 467 set_select_lines_connected(select); 468 } 469 470 upd72065_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 471 472 virtual void map(address_map &map) override; 473 virtual void auxcmd_w(uint8_t data); 474 475 protected: 476 upd72065_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); 477 }; 478 479 class upd72067_device : public upd72065_device { 480 public: 481 upd72067_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 482 483 virtual void auxcmd_w(uint8_t data) override; 484 }; 485 486 class upd72069_device : public upd72065_device { 487 public: 488 upd72069_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 489 }; 490 491 class n82077aa_device : public ps2_fdc_device { 492 public: n82077aa_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,mode_t mode)493 n82077aa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, mode_t mode) 494 : n82077aa_device(mconfig, tag, owner, clock) 495 { 496 set_mode(mode); 497 } 498 n82077aa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 499 500 virtual void map(address_map &map) override; 501 }; 502 503 class pc_fdc_superio_device : public upd765_family_device { 504 public: 505 pc_fdc_superio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 506 507 virtual void map(address_map &map) override; 508 }; 509 510 class dp8473_device : public upd765_family_device { 511 public: 512 dp8473_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 513 514 virtual void map(address_map &map) override; 515 }; 516 517 class pc8477a_device : public ps2_fdc_device { 518 public: pc8477a_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,mode_t mode)519 pc8477a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, mode_t mode) 520 : pc8477a_device(mconfig, tag, owner, clock) 521 { 522 set_mode(mode); 523 } 524 pc8477a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 525 526 virtual void map(address_map &map) override; 527 }; 528 529 class wd37c65c_device : public upd765_family_device { 530 public: 531 wd37c65c_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 532 533 template <typename X> wd37c65c_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,X && clock2)534 wd37c65c_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, X &&clock2) 535 : wd37c65c_device(mconfig, tag, owner, clock) 536 { 537 set_clock2(std::forward<X>(clock2)); 538 } 539 set_clock2(uint32_t clock)540 void set_clock2(uint32_t clock) { m_clock2 = clock; } set_clock2(const XTAL & xtal)541 void set_clock2(const XTAL &xtal) { set_clock2(xtal.value()); } 542 543 virtual void map(address_map &map) override; 544 virtual uint8_t get_st3(floppy_info &fi) override; 545 546 private: 547 uint32_t m_clock2; 548 }; 549 550 class mcs3201_device : public upd765_family_device { 551 public: 552 mcs3201_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 553 554 // configuration helpers input_handler()555 auto input_handler() { return m_input_handler.bind(); } 556 557 virtual void map(address_map &map) override; 558 uint8_t input_r(); 559 560 protected: 561 virtual void device_start() override; 562 563 private: 564 devcb_read8 m_input_handler; 565 }; 566 567 class tc8566af_device : public upd765_family_device { 568 public: 569 tc8566af_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 570 571 virtual void map(address_map &map) override; 572 573 void cr1_w(uint8_t data); 574 575 protected: 576 virtual void device_start() override; 577 578 private: 579 uint8_t m_cr1; 580 }; 581 582 DECLARE_DEVICE_TYPE(UPD765A, upd765a_device) 583 DECLARE_DEVICE_TYPE(UPD765B, upd765b_device) 584 DECLARE_DEVICE_TYPE(I8272A, i8272a_device) 585 DECLARE_DEVICE_TYPE(UPD72065, upd72065_device) 586 DECLARE_DEVICE_TYPE(UPD72067, upd72067_device) 587 DECLARE_DEVICE_TYPE(UPD72069, upd72069_device) 588 DECLARE_DEVICE_TYPE(I82072, i82072_device) 589 DECLARE_DEVICE_TYPE(SMC37C78, smc37c78_device) 590 DECLARE_DEVICE_TYPE(N82077AA, n82077aa_device) 591 DECLARE_DEVICE_TYPE(PC_FDC_SUPERIO, pc_fdc_superio_device) 592 DECLARE_DEVICE_TYPE(DP8473, dp8473_device) 593 DECLARE_DEVICE_TYPE(PC8477A, pc8477a_device) 594 DECLARE_DEVICE_TYPE(WD37C65C, wd37c65c_device) 595 DECLARE_DEVICE_TYPE(MCS3201, mcs3201_device) 596 DECLARE_DEVICE_TYPE(TC8566AF, tc8566af_device) 597 598 #endif // MAME_DEVICES_MACHINE_UPD765_H 599