summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/machine/upd765.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mess/machine/upd765.h')
-rw-r--r--src/mess/machine/upd765.h557
1 files changed, 388 insertions, 169 deletions
diff --git a/src/mess/machine/upd765.h b/src/mess/machine/upd765.h
index cac6bee3649..f7fd07b5506 100644
--- a/src/mess/machine/upd765.h
+++ b/src/mess/machine/upd765.h
@@ -1,215 +1,434 @@
-/***************************************************************************
+#ifndef __UPD765_F_H__
+#define __UPD765_F_H__
- machine/upd765.h
+#include "emu.h"
+#include "imagedev/floppy.h"
- Functions to emulate a NEC upd765/Intel 8272 compatible
- floppy disk controller
+/*
+ * ready = true if the ready line is physically connected to the floppy drive
+ * select = true if the fdc controls the floppy drive selection
+ * mode = MODE_AT, MODE_PS2 or MODE_M30 for the fdcs that have reset-time selection
+ */
-***************************************************************************/
+#define MCFG_UPD765A_ADD(_tag, _ready, _select) \
+ MCFG_DEVICE_ADD(_tag, UPD765A, 0) \
+ downcast<upd765a_device *>(device)->set_ready_line_connected(_ready); \
+ downcast<upd765a_device *>(device)->set_select_lines_connected(_select);
-#ifndef __UPD765_H__
-#define __UPD765_H__
+#define MCFG_UPD765B_ADD(_tag, _ready, _select) \
+ MCFG_DEVICE_ADD(_tag, UPD765B, 0) \
+ downcast<upd765b_device *>(device)->set_ready_line_connected(_ready); \
+ downcast<upd765b_device *>(device)->set_select_lines_connected(_select);
-#include "devcb.h"
-#include "imagedev/flopdrv.h"
+#define MCFG_I8272A_ADD(_tag, _ready) \
+ MCFG_DEVICE_ADD(_tag, I8272A, 0) \
+ downcast<i8272a_device *>(device)->set_ready_line_connected(_ready);
+#define MCFG_UPD72065_ADD(_tag, _ready, _select) \
+ MCFG_DEVICE_ADD(_tag, UPD72065, 0) \
+ downcast<upd72065_device *>(device)->set_ready_line_connected(_ready); \
+ downcast<upd72065_device *>(device)->set_select_lines_connected(_select);
-/***************************************************************************
- MACROS
-***************************************************************************/
+#define MCFG_SMC37C78_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, SMC37C78, 0)
-class upd765a_device : public device_t
-{
-public:
- upd765a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
- upd765a_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
- ~upd765a_device() { global_free(m_token); }
-
- // access to legacy token
- void *token() const { assert(m_token != NULL); return m_token; }
-protected:
- // device-level overrides
- virtual void device_config_complete();
- virtual void device_start();
- virtual void device_reset();
-private:
- // internal state
- void *m_token;
-};
-
-extern const device_type UPD765A;
-
-class upd765b_device : public upd765a_device
-{
-public:
- upd765b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-protected:
- // device-level overrides
- virtual void device_start();
-};
-
-extern const device_type UPD765B;
-
-class smc37c78_device : public upd765a_device
-{
-public:
- smc37c78_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-protected:
- // device-level overrides
- virtual void device_start();
-};
+#define MCFG_N82077AA_ADD(_tag, _mode) \
+ MCFG_DEVICE_ADD(_tag, N82077AA, 0) \
+ downcast<n82077aa_device *>(device)->set_mode(_mode);
-extern const device_type SMC37C78;
+#define MCFG_PC_FDC_SUPERIO_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, PC_FDC_SUPERIO, 0)
-class upd72065_device : public upd765a_device
-{
+/* Interface required for PC ISA wrapping */
+class pc_fdc_interface : public device_t {
public:
- upd72065_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-protected:
- // device-level overrides
- virtual void device_start();
-};
-
-extern const device_type UPD72065;
-
-
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
-/* RDY pin connected state */
-enum UPD765_RDY_PIN
-{
- UPD765_RDY_PIN_NOT_CONNECTED = 0,
- UPD765_RDY_PIN_CONNECTED = 1
-};
-
-#define UPD765_DAM_DELETED_DATA 0x0f8
-#define UPD765_DAM_DATA 0x0fb
-
-typedef device_t *(*upd765_get_image_func)(device_t *device, int floppy_index);
-#define UPD765_GET_IMAGE(name) device_t *name(device_t *device, int floppy_index )
+ typedef delegate<void (bool state)> line_cb;
+ typedef delegate<UINT8 ()> byte_read_cb;
+ typedef delegate<void (UINT8)> byte_write_cb;
+ pc_fdc_interface(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, type, name, tag, owner, clock) {}
-struct upd765_interface
-{
- /* interrupt issued */
- devcb_write_line out_int_func;
+ virtual void setup_intrq_cb(line_cb cb) = 0;
+ virtual void setup_drq_cb(line_cb cb) = 0;
- /* dma data request */
- devcb_write_line out_drq_func;
+ /* Note that the address map must cover and handle the whole 0-7
+ * range. The upd765, while conforming to the rest of the
+ * interface, is not eligible as a result.
+ */
- /* image lookup */
- upd765_get_image_func get_image;
+ virtual DECLARE_ADDRESS_MAP(map, 8) = 0;
- UPD765_RDY_PIN rdy_pin;
+ virtual UINT8 dma_r() = 0;
+ virtual void dma_w(UINT8 data) = 0;
- const char *floppy_drive_tags[4];
+ virtual void tc_w(bool val) = 0;
+ virtual UINT8 do_dir_r() = 0;
};
+class upd765_family_device : public pc_fdc_interface {
+public:
+ enum { MODE_AT, MODE_PS2, MODE_M30 };
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-/* read of data register */
-DECLARE_READ8_DEVICE_HANDLER(upd765_data_r);
-/* write to data register */
-DECLARE_WRITE8_DEVICE_HANDLER(upd765_data_w);
-/* read of main status register */
-DECLARE_READ8_DEVICE_HANDLER(upd765_status_r);
+ upd765_family_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
-/* dma acknowledge with write */
-DECLARE_WRITE8_DEVICE_HANDLER(upd765_dack_w);
-/* dma acknowledge with read */
-DECLARE_READ8_DEVICE_HANDLER(upd765_dack_r);
+ void setup_intrq_cb(line_cb cb);
+ void setup_drq_cb(line_cb cb);
-/* reset upd765 */
-void upd765_reset(device_t *device, int);
+ virtual DECLARE_ADDRESS_MAP(map, 8) = 0;
-/* reset pin of upd765 */
-WRITE_LINE_DEVICE_HANDLER(upd765_reset_w);
+ DECLARE_READ8_MEMBER (sra_r);
+ DECLARE_READ8_MEMBER (srb_r);
+ DECLARE_READ8_MEMBER (dor_r);
+ DECLARE_WRITE8_MEMBER(dor_w);
+ DECLARE_READ8_MEMBER (tdr_r);
+ DECLARE_WRITE8_MEMBER(tdr_w);
+ DECLARE_READ8_MEMBER (msr_r);
+ DECLARE_WRITE8_MEMBER(dsr_w);
+ DECLARE_READ8_MEMBER (fifo_r);
+ DECLARE_WRITE8_MEMBER(fifo_w);
+ DECLARE_READ8_MEMBER (dir_r);
+ DECLARE_WRITE8_MEMBER(ccr_w);
-/* set upd765 terminal count input state */
-WRITE_LINE_DEVICE_HANDLER(upd765_tc_w);
+ virtual UINT8 do_dir_r();
-/* set upd765 ready input*/
-WRITE_LINE_DEVICE_HANDLER(upd765_ready_w);
+ UINT8 dma_r();
+ void dma_w(UINT8 data);
-void upd765_idle(device_t *device);
-void upd765_set_bad(device_t *device, int state);
+ // Same as the previous ones, but as memory-mappable members
+ DECLARE_READ8_MEMBER(mdma_r);
+ DECLARE_WRITE8_MEMBER(mdma_w);
-READ_LINE_DEVICE_HANDLER( upd765_int_r );
-READ_LINE_DEVICE_HANDLER( upd765_drq_r );
+ bool get_irq() const;
+ bool get_drq() const;
+ void tc_w(bool val);
+ void ready_w(bool val);
-/*********************/
-/* STATUS REGISTER 1 */
+ void set_rate(int rate); // rate in bps, to be used when the fdc is externally frequency-controlled
-/* this is set if a TC signal was not received after the sector data was read */
-#define UPD765_ST1_END_OF_CYLINDER (1<<7)
-/* this is set if the sector ID being searched for is not found */
-#define UPD765_ST1_NO_DATA (1<<2)
-/* set if disc is write protected and a write/format operation was performed */
-#define UPD765_ST1_NOT_WRITEABLE (1<<1)
+ void set_mode(int mode);
+ void set_ready_line_connected(bool ready);
+ void set_select_lines_connected(bool select);
+ void set_floppy(floppy_image_device *image);
-/*********************/
-/* STATUS REGISTER 2 */
+protected:
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ enum {
+ TIMER_DRIVE_READY_POLLING = 4
+ };
+
+ enum {
+ PHASE_CMD, PHASE_EXEC, PHASE_RESULT
+ };
+
+ enum {
+ MSR_DB = 0x0f,
+ MSR_CB = 0x10,
+ MSR_EXM = 0x20,
+ MSR_DIO = 0x40,
+ MSR_RQM = 0x80,
+
+ ST0_UNIT = 0x07,
+ ST0_NR = 0x08,
+ ST0_EC = 0x10,
+ ST0_SE = 0x20,
+ ST0_FAIL = 0x40,
+ ST0_UNK = 0x80,
+ ST0_ABRT = 0xc0,
+
+ ST1_MA = 0x01,
+ ST1_NW = 0x02,
+ ST1_ND = 0x04,
+ ST1_OR = 0x10,
+ ST1_DE = 0x20,
+ ST1_EN = 0x80,
+
+ ST2_MD = 0x01,
+ ST2_BC = 0x02,
+ ST2_SN = 0x04,
+ ST2_SH = 0x08,
+ ST2_WC = 0x10,
+ ST2_DD = 0x20,
+ ST2_CM = 0x40,
+
+ ST3_UNIT = 0x07,
+ ST3_TS = 0x08,
+ ST3_T0 = 0x10,
+ ST3_RY = 0x20,
+ ST3_WP = 0x40,
+ ST3_FT = 0x80,
+
+ FIF_THR = 0x0f,
+ FIF_POLL = 0x10,
+ FIF_DIS = 0x20,
+ FIF_EIS = 0x40,
+
+ SPEC_ND = 0x0001,
+ };
+
+
+ enum {
+ // General "doing nothing" state
+ IDLE,
+
+ // Main states
+ RECALIBRATE,
+ SEEK,
+ READ_DATA,
+ WRITE_DATA,
+ READ_TRACK,
+ FORMAT_TRACK,
+ READ_ID,
+
+ // Sub-states
+ COMMAND_DONE,
+
+ SEEK_MOVE,
+ SEEK_WAIT_STEP_SIGNAL_TIME,
+ SEEK_WAIT_STEP_SIGNAL_TIME_DONE,
+ SEEK_WAIT_STEP_TIME,
+ SEEK_WAIT_STEP_TIME_DONE,
+ SEEK_DONE,
+
+ HEAD_LOAD_DONE,
+
+ WAIT_INDEX,
+ WAIT_INDEX_DONE,
+
+ SCAN_ID,
+ SCAN_ID_FAILED,
+
+ SECTOR_READ,
+ SECTOR_WRITTEN,
+ TC_DONE,
+
+ TRACK_DONE,
+
+ // Live states
+ SEARCH_ADDRESS_MARK_HEADER,
+ READ_HEADER_BLOCK_HEADER,
+ READ_DATA_BLOCK_HEADER,
+ READ_ID_BLOCK,
+ SEARCH_ADDRESS_MARK_DATA,
+ SEARCH_ADDRESS_MARK_DATA_FAILED,
+ READ_SECTOR_DATA,
+ READ_SECTOR_DATA_BYTE,
+
+ WRITE_SECTOR_SKIP_GAP2,
+ WRITE_SECTOR_SKIP_GAP2_BYTE,
+ WRITE_SECTOR_DATA,
+ WRITE_SECTOR_DATA_BYTE,
+
+ WRITE_TRACK_PRE_SECTORS,
+ WRITE_TRACK_PRE_SECTORS_BYTE,
+
+ WRITE_TRACK_SECTOR,
+ WRITE_TRACK_SECTOR_BYTE,
+
+ WRITE_TRACK_POST_SECTORS,
+ WRITE_TRACK_POST_SECTORS_BYTE,
+ };
+
+ struct pll_t {
+ attotime ctime, period, min_period, max_period, period_adjust_base, phase_adjust;
+
+ attotime write_start_time;
+ attotime write_buffer[32];
+ int write_position;
+ int freq_hist;
+
+ void set_clock(attotime period);
+ void reset(attotime when);
+ int get_next_bit(attotime &tm, floppy_image_device *floppy, attotime limit);
+ bool write_next_bit(bool bit, attotime &tm, floppy_image_device *floppy, attotime limit);
+ void start_writing(attotime tm);
+ void commit(floppy_image_device *floppy, attotime tm);
+ void stop_writing(floppy_image_device *floppy, attotime tm);
+ };
+
+ struct floppy_info {
+ emu_timer *tm;
+ floppy_image_device *dev;
+ int id;
+ int main_state, sub_state;
+ int dir, counter;
+ UINT8 pcn;
+ bool irq_seek, live, index, ready, irq_polled;
+ };
+
+ struct live_info {
+ enum { PT_NONE, PT_CRC_1, PT_CRC_2 };
+
+ attotime tm;
+ int state, next_state;
+ floppy_info *fi;
+ UINT16 shift_reg;
+ UINT16 crc;
+ int bit_counter, byte_counter, previous_type;
+ bool data_separator_phase, data_bit_context;
+ UINT8 data_reg;
+ UINT8 idbuf[6];
+ pll_t pll;
+ };
+
+ static int rates[4];
+
+ bool ready_connected, ready_polled, select_connected;
+
+ bool external_ready;
+
+ int mode;
+ int main_phase;
+
+ live_info cur_live, checkpoint_live;
+ line_cb intrq_cb, drq_cb;
+ bool cur_irq, data_irq, drq, internal_drq, tc, tc_done;
+ floppy_info flopi[4];
+
+ int fifo_pos, fifo_expected, command_pos, result_pos;
+ bool fifo_write;
+ UINT8 dor, dsr, msr, fifo[16], command[16], result[16];
+ UINT8 st0, st1, st2, st3;
+ UINT8 fifocfg, dor_reset;
+ UINT16 spec;
+ int sector_size;
+ int cur_rate;
+
+ emu_timer *poll_timer;
+
+ static astring tts(attotime t);
+ astring ttsn();
+
+ enum {
+ C_CONFIGURE,
+ C_FORMAT_TRACK,
+ C_PERPENDICULAR,
+ C_READ_DATA,
+ C_READ_ID,
+ C_READ_TRACK,
+ C_RECALIBRATE,
+ C_SEEK,
+ C_SENSE_DRIVE_STATUS,
+ C_SENSE_INTERRUPT_STATUS,
+ C_SPECIFY,
+ C_WRITE_DATA,
+
+ C_INVALID,
+ C_INCOMPLETE,
+ };
+
+ void delay_cycles(emu_timer *tm, int cycles);
+ void check_irq();
+ void fifo_expect(int size, bool write);
+ void fifo_push(UINT8 data, bool internal);
+ UINT8 fifo_pop(bool internal);
+ void set_drq(bool state);
+ bool get_ready(int fid);
+
+ void enable_transfer();
+ void disable_transfer();
+ int calc_sector_size(UINT8 size);
+
+ void run_drive_ready_polling();
+
+ int check_command();
+ void start_command(int cmd);
+ void command_end(floppy_info &fi, bool data_completion);
+
+ void recalibrate_start(floppy_info &fi);
+ void seek_start(floppy_info &fi);
+ void seek_continue(floppy_info &fi);
+
+ void read_data_start(floppy_info &fi);
+ void read_data_continue(floppy_info &fi);
+
+ void write_data_start(floppy_info &fi);
+ void write_data_continue(floppy_info &fi);
+
+ void read_track_start(floppy_info &fi);
+ void read_track_continue(floppy_info &fi);
+
+ void format_track_start(floppy_info &fi);
+ void format_track_continue(floppy_info &fi);
+
+ void read_id_start(floppy_info &fi);
+ void read_id_continue(floppy_info &fi);
+
+ void general_continue(floppy_info &fi);
+ void index_callback(floppy_image_device *floppy, int state);
+ bool sector_matches() const;
+
+ void live_start(floppy_info &fi, int live_state);
+ void live_abort();
+ void checkpoint();
+ void rollback();
+ void live_delay(int state);
+ void live_sync();
+ void live_run(attotime limit = attotime::never);
+ void live_write_raw(UINT16 raw);
+ void live_write_mfm(UINT8 mfm);
+
+ bool read_one_bit(attotime limit);
+ bool write_one_bit(attotime limit);
+};
-/* C parameter specified did not match C value read from disc */
-#define UPD765_ST2_WRONG_CYLINDER (1<<4)
-/* C parameter specified did not match C value read from disc, and C read from disc was 0x0ff */
-#define UPD765_ST2_BAD_CYLINDER (1<<1)
-/* this is set if the FDC encounters a Deleted Data Mark when executing a read data
-command, or FDC encounters a Data Mark when executing a read deleted data command */
-#define UPD765_ST2_CONTROL_MARK (1<<6)
+class upd765a_device : public upd765_family_device {
+public:
+ upd765a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-/***************************************************************************
- DEVICE CONFIGURATION MACROS
-***************************************************************************/
+ virtual DECLARE_ADDRESS_MAP(map, 8);
+};
-#define MCFG_UPD765A_ADD(_tag, _intrf) \
- MCFG_DEVICE_ADD(_tag, UPD765A, 0) \
- MCFG_DEVICE_CONFIG(_intrf)
+class upd765b_device : public upd765_family_device {
+public:
+ upd765b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-#define MCFG_UPD765A_MODIFY(_tag, _intrf) \
- MCFG_DEVICE_MODIFY(_tag) \
- MCFG_DEVICE_CONFIG(_intrf)
+ virtual DECLARE_ADDRESS_MAP(map, 8);
+};
-#define MCFG_UPD765A_REMOVE(_tag) \
- MCFG_DEVICE_REMOVE(_tag)
+class i8272a_device : public upd765_family_device {
+public:
+ i8272a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-#define MCFG_UPD765B_ADD(_tag, _intrf) \
- MCFG_DEVICE_ADD(_tag, UPD765B, 0) \
- MCFG_DEVICE_CONFIG(_intrf)
+ virtual DECLARE_ADDRESS_MAP(map, 8);
+};
-#define MCFG_UPD765B_MODIFY(_tag, _intrf) \
- MCFG_DEVICE_MODIFY(_tag) \
- MCFG_DEVICE_CONFIG(_intrf)
+class smc37c78_device : public upd765_family_device {
+public:
+ smc37c78_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-#define MCFG_UPD765B_REMOVE(_tag) \
- MCFG_DEVICE_REMOVE(_tag)
+ virtual DECLARE_ADDRESS_MAP(map, 8);
+};
-#define MCFG_SMC37C78_ADD(_tag, _intrf) \
- MCFG_DEVICE_ADD(_tag, SMC37C78, 0) \
- MCFG_DEVICE_CONFIG(_intrf)
+class upd72065_device : public upd765_family_device {
+public:
+ upd72065_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-#define MCFG_SMC37C78_MODIFY(_tag, _intrf) \
- MCFG_DEVICE_MODIFY(_tag) \
- MCFG_DEVICE_CONFIG(_intrf)
+ virtual DECLARE_ADDRESS_MAP(map, 8);
+};
-#define MCFG_SMC37C78_REMOVE(_tag) \
- MCFG_DEVICE_REMOVE(_tag)
+class n82077aa_device : public upd765_family_device {
+public:
+ n82077aa_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-#define MCFG_UPD72065_ADD(_tag, _intrf) \
- MCFG_DEVICE_ADD(_tag, UPD72065, 0) \
- MCFG_DEVICE_CONFIG(_intrf)
+ virtual DECLARE_ADDRESS_MAP(map, 8);
+};
-#define MCFG_UPD72065_MODIFY(_tag, _intrf) \
- MCFG_DEVICE_MODIFY(_tag) \
- MCFG_DEVICE_CONFIG(_intrf)
+class pc_fdc_superio_device : public upd765_family_device {
+public:
+ pc_fdc_superio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-#define MCFG_UPD72065_REMOVE(_tag) \
- MCFG_DEVICE_REMOVE(_tag)
+ virtual DECLARE_ADDRESS_MAP(map, 8);
+};
+extern const device_type UPD765A;
+extern const device_type UPD765B;
+extern const device_type I8272A;
+extern const device_type UPD72065;
+extern const device_type SMC37C78;
+extern const device_type N82077AA;
+extern const device_type PC_FDC_SUPERIO;
-#endif /* __UPD765_H__ */
+#endif