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