mirror of
https://github.com/holub/mame
synced 2025-07-03 00:56:03 +03:00
upd765, wd1772: Move to emu [O. Galibert]
This commit is contained in:
parent
13673729a4
commit
b3d0193b66
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -7317,8 +7317,6 @@ src/mess/machine/upd7002.c svneol=native#text/plain
|
|||||||
src/mess/machine/upd7002.h svneol=native#text/plain
|
src/mess/machine/upd7002.h svneol=native#text/plain
|
||||||
src/mess/machine/upd71071.c svneol=native#text/plain
|
src/mess/machine/upd71071.c svneol=native#text/plain
|
||||||
src/mess/machine/upd71071.h svneol=native#text/plain
|
src/mess/machine/upd71071.h svneol=native#text/plain
|
||||||
src/mess/machine/upd765.c svneol=native#text/plain
|
|
||||||
src/mess/machine/upd765.h svneol=native#text/plain
|
|
||||||
src/mess/machine/ut88.c svneol=native#text/plain
|
src/mess/machine/ut88.c svneol=native#text/plain
|
||||||
src/mess/machine/v1050kb.c svneol=native#text/plain
|
src/mess/machine/v1050kb.c svneol=native#text/plain
|
||||||
src/mess/machine/v1050kb.h svneol=native#text/plain
|
src/mess/machine/v1050kb.h svneol=native#text/plain
|
||||||
@ -7412,8 +7410,6 @@ src/mess/machine/wangpckb.c svneol=native#text/plain
|
|||||||
src/mess/machine/wangpckb.h svneol=native#text/plain
|
src/mess/machine/wangpckb.h svneol=native#text/plain
|
||||||
src/mess/machine/wd11c00_17.c svneol=native#text/plain
|
src/mess/machine/wd11c00_17.c svneol=native#text/plain
|
||||||
src/mess/machine/wd11c00_17.h svneol=native#text/plain
|
src/mess/machine/wd11c00_17.h svneol=native#text/plain
|
||||||
src/mess/machine/wd1772.c svneol=native#text/plain
|
|
||||||
src/mess/machine/wd1772.h svneol=native#text/plain
|
|
||||||
src/mess/machine/wd2010.c svneol=native#text/plain
|
src/mess/machine/wd2010.c svneol=native#text/plain
|
||||||
src/mess/machine/wd2010.h svneol=native#text/plain
|
src/mess/machine/wd2010.h svneol=native#text/plain
|
||||||
src/mess/machine/wswan.c svneol=native#text/plain
|
src/mess/machine/wswan.c svneol=native#text/plain
|
||||||
|
@ -269,7 +269,9 @@ EMUMACHINEOBJS = \
|
|||||||
$(EMUMACHINE)/upd1990a.o \
|
$(EMUMACHINE)/upd1990a.o \
|
||||||
$(EMUMACHINE)/upd4701.o \
|
$(EMUMACHINE)/upd4701.o \
|
||||||
$(EMUMACHINE)/upd7201.o \
|
$(EMUMACHINE)/upd7201.o \
|
||||||
|
$(EMUMACHINE)/upd765.o \
|
||||||
$(EMUMACHINE)/v3021.o \
|
$(EMUMACHINE)/v3021.o \
|
||||||
|
$(EMUMACHINE)/wd1772.o \
|
||||||
$(EMUMACHINE)/wd17xx.o \
|
$(EMUMACHINE)/wd17xx.o \
|
||||||
$(EMUMACHINE)/wd33c93.o \
|
$(EMUMACHINE)/wd33c93.o \
|
||||||
$(EMUMACHINE)/x2212.o \
|
$(EMUMACHINE)/x2212.o \
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,441 @@
|
|||||||
|
#ifndef __UPD765_F_H__
|
||||||
|
#define __UPD765_F_H__
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
#include "imagedev/floppy.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
#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);
|
||||||
|
|
||||||
|
#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);
|
||||||
|
|
||||||
|
#define MCFG_SMC37C78_ADD(_tag) \
|
||||||
|
MCFG_DEVICE_ADD(_tag, SMC37C78, 0)
|
||||||
|
|
||||||
|
#define MCFG_N82077AA_ADD(_tag, _mode) \
|
||||||
|
MCFG_DEVICE_ADD(_tag, N82077AA, 0) \
|
||||||
|
downcast<n82077aa_device *>(device)->set_mode(_mode);
|
||||||
|
|
||||||
|
#define MCFG_PC_FDC_SUPERIO_ADD(_tag) \
|
||||||
|
MCFG_DEVICE_ADD(_tag, PC_FDC_SUPERIO, 0)
|
||||||
|
|
||||||
|
/* Interface required for PC ISA wrapping */
|
||||||
|
class pc_fdc_interface : public device_t {
|
||||||
|
public:
|
||||||
|
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) {}
|
||||||
|
|
||||||
|
virtual void setup_intrq_cb(line_cb cb) = 0;
|
||||||
|
virtual void setup_drq_cb(line_cb cb) = 0;
|
||||||
|
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual DECLARE_ADDRESS_MAP(map, 8) = 0;
|
||||||
|
|
||||||
|
virtual UINT8 dma_r() = 0;
|
||||||
|
virtual void dma_w(UINT8 data) = 0;
|
||||||
|
|
||||||
|
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 };
|
||||||
|
|
||||||
|
upd765_family_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
void setup_intrq_cb(line_cb cb);
|
||||||
|
void setup_drq_cb(line_cb cb);
|
||||||
|
|
||||||
|
virtual DECLARE_ADDRESS_MAP(map, 8) = 0;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
virtual UINT8 do_dir_r();
|
||||||
|
|
||||||
|
UINT8 dma_r();
|
||||||
|
void dma_w(UINT8 data);
|
||||||
|
|
||||||
|
// Same as the previous ones, but as memory-mappable members
|
||||||
|
DECLARE_READ8_MEMBER(mdma_r);
|
||||||
|
DECLARE_WRITE8_MEMBER(mdma_w);
|
||||||
|
|
||||||
|
bool get_irq() const;
|
||||||
|
bool get_drq() const;
|
||||||
|
void tc_w(bool val);
|
||||||
|
void ready_w(bool val);
|
||||||
|
|
||||||
|
void set_rate(int rate); // rate in bps, to be used when the fdc is externally frequency-controlled
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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 {
|
||||||
|
enum { IRQ_NONE, IRQ_SEEK, IRQ_POLLED };
|
||||||
|
emu_timer *tm;
|
||||||
|
floppy_image_device *dev;
|
||||||
|
int id;
|
||||||
|
int main_state, sub_state;
|
||||||
|
int dir, counter;
|
||||||
|
UINT8 pcn;
|
||||||
|
int irq;
|
||||||
|
bool live, index, ready;
|
||||||
|
};
|
||||||
|
|
||||||
|
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, polled_irq, data_irq, drq, internal_drq, tc, tc_done, locked, mfm;
|
||||||
|
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;
|
||||||
|
UINT8 precomp, perpmode;
|
||||||
|
UINT16 spec;
|
||||||
|
int sector_size;
|
||||||
|
int cur_rate;
|
||||||
|
|
||||||
|
emu_timer *poll_timer;
|
||||||
|
|
||||||
|
static astring tts(attotime t);
|
||||||
|
astring ttsn();
|
||||||
|
|
||||||
|
enum {
|
||||||
|
C_CONFIGURE,
|
||||||
|
C_DUMP_REG,
|
||||||
|
C_FORMAT_TRACK,
|
||||||
|
C_LOCK,
|
||||||
|
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 soft_reset();
|
||||||
|
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_fm(UINT8 fm);
|
||||||
|
void live_write_mfm(UINT8 mfm);
|
||||||
|
|
||||||
|
bool read_one_bit(attotime limit);
|
||||||
|
bool write_one_bit(attotime limit);
|
||||||
|
};
|
||||||
|
|
||||||
|
class upd765a_device : public upd765_family_device {
|
||||||
|
public:
|
||||||
|
upd765a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
virtual DECLARE_ADDRESS_MAP(map, 8);
|
||||||
|
};
|
||||||
|
|
||||||
|
class upd765b_device : public upd765_family_device {
|
||||||
|
public:
|
||||||
|
upd765b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
virtual DECLARE_ADDRESS_MAP(map, 8);
|
||||||
|
};
|
||||||
|
|
||||||
|
class i8272a_device : public upd765_family_device {
|
||||||
|
public:
|
||||||
|
i8272a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
virtual DECLARE_ADDRESS_MAP(map, 8);
|
||||||
|
};
|
||||||
|
|
||||||
|
class smc37c78_device : public upd765_family_device {
|
||||||
|
public:
|
||||||
|
smc37c78_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
virtual DECLARE_ADDRESS_MAP(map, 8);
|
||||||
|
};
|
||||||
|
|
||||||
|
class upd72065_device : public upd765_family_device {
|
||||||
|
public:
|
||||||
|
upd72065_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
virtual DECLARE_ADDRESS_MAP(map, 8);
|
||||||
|
};
|
||||||
|
|
||||||
|
class n82077aa_device : public upd765_family_device {
|
||||||
|
public:
|
||||||
|
n82077aa_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
virtual DECLARE_ADDRESS_MAP(map, 8);
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,431 @@
|
|||||||
|
#ifndef WD1772_H
|
||||||
|
#define WD1772_H
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
#include "imagedev/floppy.h"
|
||||||
|
|
||||||
|
#define MCFG_FD1771x_ADD(_tag, _clock) \
|
||||||
|
MCFG_DEVICE_ADD(_tag, FD1771x, _clock)
|
||||||
|
|
||||||
|
#define MCFG_FD1793x_ADD(_tag, _clock) \
|
||||||
|
MCFG_DEVICE_ADD(_tag, FD1793x, _clock)
|
||||||
|
|
||||||
|
#define MCFG_FD1797x_ADD(_tag, _clock) \
|
||||||
|
MCFG_DEVICE_ADD(_tag, FD1797x, _clock)
|
||||||
|
|
||||||
|
#define MCFG_WD2793x_ADD(_tag, _clock) \
|
||||||
|
MCFG_DEVICE_ADD(_tag, WD2793x, _clock)
|
||||||
|
|
||||||
|
#define MCFG_WD2797x_ADD(_tag, _clock) \
|
||||||
|
MCFG_DEVICE_ADD(_tag, WD2797x, _clock)
|
||||||
|
|
||||||
|
#define MCFG_WD1770x_ADD(_tag, _clock) \
|
||||||
|
MCFG_DEVICE_ADD(_tag, WD1770x, _clock)
|
||||||
|
|
||||||
|
#define MCFG_WD1772x_ADD(_tag, _clock) \
|
||||||
|
MCFG_DEVICE_ADD(_tag, WD1772x, _clock)
|
||||||
|
|
||||||
|
#define MCFG_WD1773x_ADD(_tag, _clock) \
|
||||||
|
MCFG_DEVICE_ADD(_tag, WD1773x, _clock)
|
||||||
|
|
||||||
|
class wd177x_t : public device_t {
|
||||||
|
public:
|
||||||
|
typedef delegate<void (bool state)> line_cb;
|
||||||
|
|
||||||
|
wd177x_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
void dden_w(bool dden);
|
||||||
|
void set_floppy(floppy_image_device *floppy);
|
||||||
|
void setup_intrq_cb(line_cb cb);
|
||||||
|
void setup_drq_cb(line_cb cb);
|
||||||
|
void setup_hld_cb(line_cb cb);
|
||||||
|
void setup_enp_cb(line_cb cb);
|
||||||
|
|
||||||
|
void cmd_w(UINT8 val);
|
||||||
|
UINT8 status_r();
|
||||||
|
DECLARE_READ8_MEMBER( status_r ) { return status_r(); }
|
||||||
|
DECLARE_WRITE8_MEMBER( cmd_w ) { cmd_w(data); }
|
||||||
|
|
||||||
|
void track_w(UINT8 val);
|
||||||
|
UINT8 track_r();
|
||||||
|
DECLARE_READ8_MEMBER( track_r ) { return track_r(); }
|
||||||
|
DECLARE_WRITE8_MEMBER( track_w ) { track_w(data); }
|
||||||
|
|
||||||
|
void sector_w(UINT8 val);
|
||||||
|
UINT8 sector_r();
|
||||||
|
DECLARE_READ8_MEMBER( sector_r ) { return sector_r(); }
|
||||||
|
DECLARE_WRITE8_MEMBER( sector_w ) { sector_w(data); }
|
||||||
|
|
||||||
|
void data_w(UINT8 val);
|
||||||
|
UINT8 data_r();
|
||||||
|
DECLARE_READ8_MEMBER( data_r ) { return data_r(); }
|
||||||
|
DECLARE_WRITE8_MEMBER( data_w ) { data_w(data); }
|
||||||
|
|
||||||
|
void gen_w(int reg, UINT8 val);
|
||||||
|
UINT8 gen_r(int reg);
|
||||||
|
DECLARE_READ8_MEMBER( read ) { return gen_r(offset);}
|
||||||
|
DECLARE_WRITE8_MEMBER( write ) { gen_w(offset,data); }
|
||||||
|
|
||||||
|
bool intrq_r();
|
||||||
|
bool drq_r();
|
||||||
|
|
||||||
|
bool hld_r();
|
||||||
|
void hlt_w(bool state);
|
||||||
|
|
||||||
|
bool enp_r();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void device_start();
|
||||||
|
virtual void device_reset();
|
||||||
|
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||||
|
|
||||||
|
virtual bool has_ready() const;
|
||||||
|
virtual bool has_motor() const = 0;
|
||||||
|
virtual bool has_head_load() const;
|
||||||
|
virtual bool has_side_check() const;
|
||||||
|
virtual bool has_side_select() const;
|
||||||
|
virtual bool has_sector_length_select() const;
|
||||||
|
virtual bool has_precompensation() const;
|
||||||
|
virtual int step_time(int mode) const;
|
||||||
|
virtual int settle_time() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum { TM_GEN, TM_CMD, TM_TRACK, TM_SECTOR };
|
||||||
|
|
||||||
|
// State machine general behaviour:
|
||||||
|
//
|
||||||
|
// There are three levels of state.
|
||||||
|
//
|
||||||
|
// Main state is associated to (groups of) commands. They're set
|
||||||
|
// by a *_start() function below, and the associated _continue()
|
||||||
|
// function can then be called at pretty much any time.
|
||||||
|
//
|
||||||
|
// Sub state is the state of execution within a command. The
|
||||||
|
// principle is that the *_start() function selects the initial
|
||||||
|
// substate, then the *_continue() function decides what to do,
|
||||||
|
// possibly changing state. Eventually it can:
|
||||||
|
// - decide to wait for an event (timer, index)
|
||||||
|
// - end the command with command_end()
|
||||||
|
// - start a live state (see below)
|
||||||
|
//
|
||||||
|
// In the first case, it must first switch to a waiting
|
||||||
|
// sub-state, then return. The waiting sub-state must just
|
||||||
|
// return immediatly when *_continue is called. Eventually the
|
||||||
|
// event handler function will advance the state machine to
|
||||||
|
// another sub-state, and things will continue synchronously.
|
||||||
|
//
|
||||||
|
// On command end it's also supposed to return immediatly.
|
||||||
|
//
|
||||||
|
// The last option is to switch to the next sub-state, start a
|
||||||
|
// live state with live_start() then return. The next sub-state
|
||||||
|
// will only be called once the live state is finished.
|
||||||
|
//
|
||||||
|
// Live states change continually depending on the disk contents
|
||||||
|
// until the next externally discernable event is found. They
|
||||||
|
// are checkpointing, run until an event is found, then they wait
|
||||||
|
// for it. When an event eventually happen the the changes are
|
||||||
|
// either committed or replayed until the sync event time.
|
||||||
|
//
|
||||||
|
// The transition to IDLE is only done on a synced event. Some
|
||||||
|
// other transitions, such as activating drq, are also done after
|
||||||
|
// syncing without exiting live mode. Syncing in live mode is
|
||||||
|
// done by calling live_delay() with the state to change to after
|
||||||
|
// syncing.
|
||||||
|
|
||||||
|
enum {
|
||||||
|
// General "doing nothing" state
|
||||||
|
IDLE,
|
||||||
|
|
||||||
|
// Main states - the commands
|
||||||
|
RESTORE,
|
||||||
|
SEEK,
|
||||||
|
STEP,
|
||||||
|
READ_SECTOR,
|
||||||
|
READ_TRACK,
|
||||||
|
READ_ID,
|
||||||
|
WRITE_TRACK,
|
||||||
|
WRITE_SECTOR,
|
||||||
|
|
||||||
|
// Sub states
|
||||||
|
|
||||||
|
SPINUP,
|
||||||
|
SPINUP_WAIT,
|
||||||
|
SPINUP_DONE,
|
||||||
|
|
||||||
|
SETTLE_WAIT,
|
||||||
|
SETTLE_DONE,
|
||||||
|
|
||||||
|
DATA_LOAD_WAIT,
|
||||||
|
DATA_LOAD_WAIT_DONE,
|
||||||
|
|
||||||
|
SEEK_MOVE,
|
||||||
|
SEEK_WAIT_STEP_TIME,
|
||||||
|
SEEK_WAIT_STEP_TIME_DONE,
|
||||||
|
SEEK_WAIT_STABILIZATION_TIME,
|
||||||
|
SEEK_WAIT_STABILIZATION_TIME_DONE,
|
||||||
|
SEEK_DONE,
|
||||||
|
|
||||||
|
WAIT_INDEX,
|
||||||
|
WAIT_INDEX_DONE,
|
||||||
|
|
||||||
|
SCAN_ID,
|
||||||
|
SCAN_ID_FAILED,
|
||||||
|
|
||||||
|
SECTOR_READ,
|
||||||
|
SECTOR_WRITE,
|
||||||
|
TRACK_DONE,
|
||||||
|
|
||||||
|
// Live states
|
||||||
|
|
||||||
|
SEARCH_ADDRESS_MARK_HEADER,
|
||||||
|
READ_HEADER_BLOCK_HEADER,
|
||||||
|
READ_DATA_BLOCK_HEADER,
|
||||||
|
READ_ID_BLOCK_TO_LOCAL,
|
||||||
|
READ_ID_BLOCK_TO_DMA,
|
||||||
|
READ_ID_BLOCK_TO_DMA_BYTE,
|
||||||
|
SEARCH_ADDRESS_MARK_DATA,
|
||||||
|
SEARCH_ADDRESS_MARK_DATA_FAILED,
|
||||||
|
READ_SECTOR_DATA,
|
||||||
|
READ_SECTOR_DATA_BYTE,
|
||||||
|
READ_TRACK_DATA,
|
||||||
|
READ_TRACK_DATA_BYTE,
|
||||||
|
WRITE_TRACK_DATA,
|
||||||
|
WRITE_BYTE,
|
||||||
|
WRITE_BYTE_DONE,
|
||||||
|
WRITE_SECTOR_PRE,
|
||||||
|
WRITE_SECTOR_PRE_BYTE,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pll_t {
|
||||||
|
UINT16 counter;
|
||||||
|
UINT16 increment;
|
||||||
|
UINT16 transition_time;
|
||||||
|
UINT8 history;
|
||||||
|
UINT8 slot;
|
||||||
|
UINT8 phase_add, phase_sub, freq_add, freq_sub;
|
||||||
|
attotime ctime;
|
||||||
|
|
||||||
|
attotime delays[42];
|
||||||
|
|
||||||
|
attotime write_start_time;
|
||||||
|
attotime write_buffer[32];
|
||||||
|
int write_position;
|
||||||
|
|
||||||
|
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 live_info {
|
||||||
|
enum { PT_NONE, PT_CRC_1, PT_CRC_2 };
|
||||||
|
|
||||||
|
attotime tm;
|
||||||
|
int state, next_state;
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
S_BUSY = 0x01,
|
||||||
|
S_DRQ = 0x02,
|
||||||
|
S_IP = 0x02,
|
||||||
|
S_TR00 = 0x04,
|
||||||
|
S_LOST = 0x04,
|
||||||
|
S_CRC = 0x08,
|
||||||
|
S_RNF = 0x10,
|
||||||
|
S_HLD = 0x20,
|
||||||
|
S_SPIN = 0x20, // WD1770, WD1772
|
||||||
|
S_DDM = 0x20,
|
||||||
|
S_WF = 0x20, // WD1773
|
||||||
|
S_WP = 0x40,
|
||||||
|
S_NRDY = 0x80,
|
||||||
|
S_MON = 0x80 // WD1770, WD1772
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
I_RDY = 0x01,
|
||||||
|
I_NRDY = 0x02,
|
||||||
|
I_IDX = 0x04,
|
||||||
|
I_IMM = 0x08
|
||||||
|
};
|
||||||
|
|
||||||
|
floppy_image_device *floppy;
|
||||||
|
|
||||||
|
emu_timer *t_gen, *t_cmd, *t_track, *t_sector;
|
||||||
|
|
||||||
|
bool dden, status_type_1, intrq, drq, hld, hlt, enp;
|
||||||
|
int main_state, sub_state;
|
||||||
|
UINT8 command, track, sector, data, status, intrq_cond;
|
||||||
|
int last_dir;
|
||||||
|
|
||||||
|
int counter, motor_timeout, sector_size;
|
||||||
|
|
||||||
|
int cmd_buffer, track_buffer, sector_buffer;
|
||||||
|
|
||||||
|
live_info cur_live, checkpoint_live;
|
||||||
|
line_cb intrq_cb, drq_cb, hld_cb, enp_cb;
|
||||||
|
|
||||||
|
static astring tts(attotime t);
|
||||||
|
astring ttsn();
|
||||||
|
|
||||||
|
void delay_cycles(emu_timer *tm, int cycles);
|
||||||
|
|
||||||
|
// Device timer subfunctions
|
||||||
|
void do_cmd_w();
|
||||||
|
void do_track_w();
|
||||||
|
void do_sector_w();
|
||||||
|
void do_generic();
|
||||||
|
|
||||||
|
|
||||||
|
// Main-state handling functions
|
||||||
|
void seek_start(int state);
|
||||||
|
void seek_continue();
|
||||||
|
|
||||||
|
void read_sector_start();
|
||||||
|
void read_sector_continue();
|
||||||
|
|
||||||
|
void read_track_start();
|
||||||
|
void read_track_continue();
|
||||||
|
|
||||||
|
void read_id_start();
|
||||||
|
void read_id_continue();
|
||||||
|
|
||||||
|
void write_track_start();
|
||||||
|
void write_track_continue();
|
||||||
|
|
||||||
|
void write_sector_start();
|
||||||
|
void write_sector_continue();
|
||||||
|
|
||||||
|
void interrupt_start();
|
||||||
|
|
||||||
|
void general_continue();
|
||||||
|
void command_end();
|
||||||
|
|
||||||
|
void spinup();
|
||||||
|
void index_callback(floppy_image_device *floppy, int state);
|
||||||
|
bool sector_matches() const;
|
||||||
|
bool is_ready();
|
||||||
|
|
||||||
|
void live_start(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);
|
||||||
|
bool read_one_bit(attotime limit);
|
||||||
|
bool write_one_bit(attotime limit);
|
||||||
|
|
||||||
|
void live_write_raw(UINT16 raw);
|
||||||
|
void live_write_mfm(UINT8 mfm);
|
||||||
|
|
||||||
|
void drop_drq();
|
||||||
|
void set_drq();
|
||||||
|
};
|
||||||
|
|
||||||
|
class fd1771_t : public wd177x_t {
|
||||||
|
public:
|
||||||
|
fd1771_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool has_ready() const { return true; }
|
||||||
|
virtual bool has_motor() const { return false; }
|
||||||
|
virtual bool has_head_load() const { return true; }
|
||||||
|
virtual bool has_side_check() const { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class fd1793_t : public wd177x_t {
|
||||||
|
public:
|
||||||
|
fd1793_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool has_ready() const { return true; }
|
||||||
|
virtual bool has_motor() const { return false; }
|
||||||
|
virtual bool has_head_load() const { return true; }
|
||||||
|
virtual bool has_side_check() const { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class fd1797_t : public wd177x_t {
|
||||||
|
public:
|
||||||
|
fd1797_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool has_ready() const { return true; }
|
||||||
|
virtual bool has_motor() const { return false; }
|
||||||
|
virtual bool has_head_load() const { return true; }
|
||||||
|
virtual bool has_side_select() const { return true; }
|
||||||
|
virtual bool has_sector_length_select() const { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class wd2793_t : public wd177x_t {
|
||||||
|
public:
|
||||||
|
wd2793_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool has_ready() const { return true; }
|
||||||
|
virtual bool has_motor() const { return false; }
|
||||||
|
virtual bool has_head_load() const { return true; }
|
||||||
|
virtual bool has_side_check() const { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class wd2797_t : public wd177x_t {
|
||||||
|
public:
|
||||||
|
wd2797_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool has_ready() const { return true; }
|
||||||
|
virtual bool has_motor() const { return false; }
|
||||||
|
virtual bool has_head_load() const { return true; }
|
||||||
|
virtual bool has_side_select() const { return true; }
|
||||||
|
virtual bool has_sector_length_select() const { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class wd1770_t : public wd177x_t {
|
||||||
|
public:
|
||||||
|
wd1770_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool has_motor() const { return true; }
|
||||||
|
virtual bool has_precompensation() const { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class wd1772_t : public wd177x_t {
|
||||||
|
public:
|
||||||
|
wd1772_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool has_motor() const { return true; }
|
||||||
|
virtual bool has_precompensation() const { return true; }
|
||||||
|
virtual int step_time(int mode) const;
|
||||||
|
virtual int settle_time() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class wd1773_t : public wd177x_t {
|
||||||
|
public:
|
||||||
|
wd1773_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool has_motor() const { return false; }
|
||||||
|
virtual bool has_head_load() const { return true; }
|
||||||
|
virtual bool has_side_check() const { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const device_type FD1771x;
|
||||||
|
extern const device_type FD1793x;
|
||||||
|
extern const device_type FD1797x;
|
||||||
|
extern const device_type WD2793x;
|
||||||
|
extern const device_type WD2797x;
|
||||||
|
extern const device_type WD1770x;
|
||||||
|
extern const device_type WD1772x;
|
||||||
|
extern const device_type WD1773x;
|
||||||
|
|
||||||
|
#endif
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "imagedev/floppy.h"
|
#include "imagedev/floppy.h"
|
||||||
#include "upd765.h"
|
#include "machine/upd765.h"
|
||||||
|
|
||||||
#define MCFG_PC_FDC_XT_ADD(_tag) \
|
#define MCFG_PC_FDC_XT_ADD(_tag) \
|
||||||
MCFG_DEVICE_ADD(_tag, PC_FDC_XT, 0)
|
MCFG_DEVICE_ADD(_tag, PC_FDC_XT, 0)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,441 +0,0 @@
|
|||||||
#ifndef __UPD765_F_H__
|
|
||||||
#define __UPD765_F_H__
|
|
||||||
|
|
||||||
#include "emu.h"
|
|
||||||
#include "imagedev/floppy.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
|
|
||||||
#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);
|
|
||||||
|
|
||||||
#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);
|
|
||||||
|
|
||||||
#define MCFG_SMC37C78_ADD(_tag) \
|
|
||||||
MCFG_DEVICE_ADD(_tag, SMC37C78, 0)
|
|
||||||
|
|
||||||
#define MCFG_N82077AA_ADD(_tag, _mode) \
|
|
||||||
MCFG_DEVICE_ADD(_tag, N82077AA, 0) \
|
|
||||||
downcast<n82077aa_device *>(device)->set_mode(_mode);
|
|
||||||
|
|
||||||
#define MCFG_PC_FDC_SUPERIO_ADD(_tag) \
|
|
||||||
MCFG_DEVICE_ADD(_tag, PC_FDC_SUPERIO, 0)
|
|
||||||
|
|
||||||
/* Interface required for PC ISA wrapping */
|
|
||||||
class pc_fdc_interface : public device_t {
|
|
||||||
public:
|
|
||||||
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) {}
|
|
||||||
|
|
||||||
virtual void setup_intrq_cb(line_cb cb) = 0;
|
|
||||||
virtual void setup_drq_cb(line_cb cb) = 0;
|
|
||||||
|
|
||||||
/* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
virtual DECLARE_ADDRESS_MAP(map, 8) = 0;
|
|
||||||
|
|
||||||
virtual UINT8 dma_r() = 0;
|
|
||||||
virtual void dma_w(UINT8 data) = 0;
|
|
||||||
|
|
||||||
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 };
|
|
||||||
|
|
||||||
upd765_family_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
|
|
||||||
|
|
||||||
void setup_intrq_cb(line_cb cb);
|
|
||||||
void setup_drq_cb(line_cb cb);
|
|
||||||
|
|
||||||
virtual DECLARE_ADDRESS_MAP(map, 8) = 0;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
virtual UINT8 do_dir_r();
|
|
||||||
|
|
||||||
UINT8 dma_r();
|
|
||||||
void dma_w(UINT8 data);
|
|
||||||
|
|
||||||
// Same as the previous ones, but as memory-mappable members
|
|
||||||
DECLARE_READ8_MEMBER(mdma_r);
|
|
||||||
DECLARE_WRITE8_MEMBER(mdma_w);
|
|
||||||
|
|
||||||
bool get_irq() const;
|
|
||||||
bool get_drq() const;
|
|
||||||
void tc_w(bool val);
|
|
||||||
void ready_w(bool val);
|
|
||||||
|
|
||||||
void set_rate(int rate); // rate in bps, to be used when the fdc is externally frequency-controlled
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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 {
|
|
||||||
enum { IRQ_NONE, IRQ_SEEK, IRQ_POLLED };
|
|
||||||
emu_timer *tm;
|
|
||||||
floppy_image_device *dev;
|
|
||||||
int id;
|
|
||||||
int main_state, sub_state;
|
|
||||||
int dir, counter;
|
|
||||||
UINT8 pcn;
|
|
||||||
int irq;
|
|
||||||
bool live, index, ready;
|
|
||||||
};
|
|
||||||
|
|
||||||
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, polled_irq, data_irq, drq, internal_drq, tc, tc_done, locked, mfm;
|
|
||||||
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;
|
|
||||||
UINT8 precomp, perpmode;
|
|
||||||
UINT16 spec;
|
|
||||||
int sector_size;
|
|
||||||
int cur_rate;
|
|
||||||
|
|
||||||
emu_timer *poll_timer;
|
|
||||||
|
|
||||||
static astring tts(attotime t);
|
|
||||||
astring ttsn();
|
|
||||||
|
|
||||||
enum {
|
|
||||||
C_CONFIGURE,
|
|
||||||
C_DUMP_REG,
|
|
||||||
C_FORMAT_TRACK,
|
|
||||||
C_LOCK,
|
|
||||||
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 soft_reset();
|
|
||||||
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_fm(UINT8 fm);
|
|
||||||
void live_write_mfm(UINT8 mfm);
|
|
||||||
|
|
||||||
bool read_one_bit(attotime limit);
|
|
||||||
bool write_one_bit(attotime limit);
|
|
||||||
};
|
|
||||||
|
|
||||||
class upd765a_device : public upd765_family_device {
|
|
||||||
public:
|
|
||||||
upd765a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
|
||||||
|
|
||||||
virtual DECLARE_ADDRESS_MAP(map, 8);
|
|
||||||
};
|
|
||||||
|
|
||||||
class upd765b_device : public upd765_family_device {
|
|
||||||
public:
|
|
||||||
upd765b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
|
||||||
|
|
||||||
virtual DECLARE_ADDRESS_MAP(map, 8);
|
|
||||||
};
|
|
||||||
|
|
||||||
class i8272a_device : public upd765_family_device {
|
|
||||||
public:
|
|
||||||
i8272a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
|
||||||
|
|
||||||
virtual DECLARE_ADDRESS_MAP(map, 8);
|
|
||||||
};
|
|
||||||
|
|
||||||
class smc37c78_device : public upd765_family_device {
|
|
||||||
public:
|
|
||||||
smc37c78_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
|
||||||
|
|
||||||
virtual DECLARE_ADDRESS_MAP(map, 8);
|
|
||||||
};
|
|
||||||
|
|
||||||
class upd72065_device : public upd765_family_device {
|
|
||||||
public:
|
|
||||||
upd72065_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
|
||||||
|
|
||||||
virtual DECLARE_ADDRESS_MAP(map, 8);
|
|
||||||
};
|
|
||||||
|
|
||||||
class n82077aa_device : public upd765_family_device {
|
|
||||||
public:
|
|
||||||
n82077aa_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
|
||||||
|
|
||||||
virtual DECLARE_ADDRESS_MAP(map, 8);
|
|
||||||
};
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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
|
|
File diff suppressed because it is too large
Load Diff
@ -1,431 +0,0 @@
|
|||||||
#ifndef WD1772_H
|
|
||||||
#define WD1772_H
|
|
||||||
|
|
||||||
#include "emu.h"
|
|
||||||
#include "imagedev/floppy.h"
|
|
||||||
|
|
||||||
#define MCFG_FD1771x_ADD(_tag, _clock) \
|
|
||||||
MCFG_DEVICE_ADD(_tag, FD1771x, _clock)
|
|
||||||
|
|
||||||
#define MCFG_FD1793x_ADD(_tag, _clock) \
|
|
||||||
MCFG_DEVICE_ADD(_tag, FD1793x, _clock)
|
|
||||||
|
|
||||||
#define MCFG_FD1797x_ADD(_tag, _clock) \
|
|
||||||
MCFG_DEVICE_ADD(_tag, FD1797x, _clock)
|
|
||||||
|
|
||||||
#define MCFG_WD2793x_ADD(_tag, _clock) \
|
|
||||||
MCFG_DEVICE_ADD(_tag, WD2793x, _clock)
|
|
||||||
|
|
||||||
#define MCFG_WD2797x_ADD(_tag, _clock) \
|
|
||||||
MCFG_DEVICE_ADD(_tag, WD2797x, _clock)
|
|
||||||
|
|
||||||
#define MCFG_WD1770x_ADD(_tag, _clock) \
|
|
||||||
MCFG_DEVICE_ADD(_tag, WD1770x, _clock)
|
|
||||||
|
|
||||||
#define MCFG_WD1772x_ADD(_tag, _clock) \
|
|
||||||
MCFG_DEVICE_ADD(_tag, WD1772x, _clock)
|
|
||||||
|
|
||||||
#define MCFG_WD1773x_ADD(_tag, _clock) \
|
|
||||||
MCFG_DEVICE_ADD(_tag, WD1773x, _clock)
|
|
||||||
|
|
||||||
class wd177x_t : public device_t {
|
|
||||||
public:
|
|
||||||
typedef delegate<void (bool state)> line_cb;
|
|
||||||
|
|
||||||
wd177x_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
|
|
||||||
|
|
||||||
void dden_w(bool dden);
|
|
||||||
void set_floppy(floppy_image_device *floppy);
|
|
||||||
void setup_intrq_cb(line_cb cb);
|
|
||||||
void setup_drq_cb(line_cb cb);
|
|
||||||
void setup_hld_cb(line_cb cb);
|
|
||||||
void setup_enp_cb(line_cb cb);
|
|
||||||
|
|
||||||
void cmd_w(UINT8 val);
|
|
||||||
UINT8 status_r();
|
|
||||||
DECLARE_READ8_MEMBER( status_r ) { return status_r(); }
|
|
||||||
DECLARE_WRITE8_MEMBER( cmd_w ) { cmd_w(data); }
|
|
||||||
|
|
||||||
void track_w(UINT8 val);
|
|
||||||
UINT8 track_r();
|
|
||||||
DECLARE_READ8_MEMBER( track_r ) { return track_r(); }
|
|
||||||
DECLARE_WRITE8_MEMBER( track_w ) { track_w(data); }
|
|
||||||
|
|
||||||
void sector_w(UINT8 val);
|
|
||||||
UINT8 sector_r();
|
|
||||||
DECLARE_READ8_MEMBER( sector_r ) { return sector_r(); }
|
|
||||||
DECLARE_WRITE8_MEMBER( sector_w ) { sector_w(data); }
|
|
||||||
|
|
||||||
void data_w(UINT8 val);
|
|
||||||
UINT8 data_r();
|
|
||||||
DECLARE_READ8_MEMBER( data_r ) { return data_r(); }
|
|
||||||
DECLARE_WRITE8_MEMBER( data_w ) { data_w(data); }
|
|
||||||
|
|
||||||
void gen_w(int reg, UINT8 val);
|
|
||||||
UINT8 gen_r(int reg);
|
|
||||||
DECLARE_READ8_MEMBER( read ) { return gen_r(offset);}
|
|
||||||
DECLARE_WRITE8_MEMBER( write ) { gen_w(offset,data); }
|
|
||||||
|
|
||||||
bool intrq_r();
|
|
||||||
bool drq_r();
|
|
||||||
|
|
||||||
bool hld_r();
|
|
||||||
void hlt_w(bool state);
|
|
||||||
|
|
||||||
bool enp_r();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void device_start();
|
|
||||||
virtual void device_reset();
|
|
||||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
|
||||||
|
|
||||||
virtual bool has_ready() const;
|
|
||||||
virtual bool has_motor() const = 0;
|
|
||||||
virtual bool has_head_load() const;
|
|
||||||
virtual bool has_side_check() const;
|
|
||||||
virtual bool has_side_select() const;
|
|
||||||
virtual bool has_sector_length_select() const;
|
|
||||||
virtual bool has_precompensation() const;
|
|
||||||
virtual int step_time(int mode) const;
|
|
||||||
virtual int settle_time() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum { TM_GEN, TM_CMD, TM_TRACK, TM_SECTOR };
|
|
||||||
|
|
||||||
// State machine general behaviour:
|
|
||||||
//
|
|
||||||
// There are three levels of state.
|
|
||||||
//
|
|
||||||
// Main state is associated to (groups of) commands. They're set
|
|
||||||
// by a *_start() function below, and the associated _continue()
|
|
||||||
// function can then be called at pretty much any time.
|
|
||||||
//
|
|
||||||
// Sub state is the state of execution within a command. The
|
|
||||||
// principle is that the *_start() function selects the initial
|
|
||||||
// substate, then the *_continue() function decides what to do,
|
|
||||||
// possibly changing state. Eventually it can:
|
|
||||||
// - decide to wait for an event (timer, index)
|
|
||||||
// - end the command with command_end()
|
|
||||||
// - start a live state (see below)
|
|
||||||
//
|
|
||||||
// In the first case, it must first switch to a waiting
|
|
||||||
// sub-state, then return. The waiting sub-state must just
|
|
||||||
// return immediatly when *_continue is called. Eventually the
|
|
||||||
// event handler function will advance the state machine to
|
|
||||||
// another sub-state, and things will continue synchronously.
|
|
||||||
//
|
|
||||||
// On command end it's also supposed to return immediatly.
|
|
||||||
//
|
|
||||||
// The last option is to switch to the next sub-state, start a
|
|
||||||
// live state with live_start() then return. The next sub-state
|
|
||||||
// will only be called once the live state is finished.
|
|
||||||
//
|
|
||||||
// Live states change continually depending on the disk contents
|
|
||||||
// until the next externally discernable event is found. They
|
|
||||||
// are checkpointing, run until an event is found, then they wait
|
|
||||||
// for it. When an event eventually happen the the changes are
|
|
||||||
// either committed or replayed until the sync event time.
|
|
||||||
//
|
|
||||||
// The transition to IDLE is only done on a synced event. Some
|
|
||||||
// other transitions, such as activating drq, are also done after
|
|
||||||
// syncing without exiting live mode. Syncing in live mode is
|
|
||||||
// done by calling live_delay() with the state to change to after
|
|
||||||
// syncing.
|
|
||||||
|
|
||||||
enum {
|
|
||||||
// General "doing nothing" state
|
|
||||||
IDLE,
|
|
||||||
|
|
||||||
// Main states - the commands
|
|
||||||
RESTORE,
|
|
||||||
SEEK,
|
|
||||||
STEP,
|
|
||||||
READ_SECTOR,
|
|
||||||
READ_TRACK,
|
|
||||||
READ_ID,
|
|
||||||
WRITE_TRACK,
|
|
||||||
WRITE_SECTOR,
|
|
||||||
|
|
||||||
// Sub states
|
|
||||||
|
|
||||||
SPINUP,
|
|
||||||
SPINUP_WAIT,
|
|
||||||
SPINUP_DONE,
|
|
||||||
|
|
||||||
SETTLE_WAIT,
|
|
||||||
SETTLE_DONE,
|
|
||||||
|
|
||||||
DATA_LOAD_WAIT,
|
|
||||||
DATA_LOAD_WAIT_DONE,
|
|
||||||
|
|
||||||
SEEK_MOVE,
|
|
||||||
SEEK_WAIT_STEP_TIME,
|
|
||||||
SEEK_WAIT_STEP_TIME_DONE,
|
|
||||||
SEEK_WAIT_STABILIZATION_TIME,
|
|
||||||
SEEK_WAIT_STABILIZATION_TIME_DONE,
|
|
||||||
SEEK_DONE,
|
|
||||||
|
|
||||||
WAIT_INDEX,
|
|
||||||
WAIT_INDEX_DONE,
|
|
||||||
|
|
||||||
SCAN_ID,
|
|
||||||
SCAN_ID_FAILED,
|
|
||||||
|
|
||||||
SECTOR_READ,
|
|
||||||
SECTOR_WRITE,
|
|
||||||
TRACK_DONE,
|
|
||||||
|
|
||||||
// Live states
|
|
||||||
|
|
||||||
SEARCH_ADDRESS_MARK_HEADER,
|
|
||||||
READ_HEADER_BLOCK_HEADER,
|
|
||||||
READ_DATA_BLOCK_HEADER,
|
|
||||||
READ_ID_BLOCK_TO_LOCAL,
|
|
||||||
READ_ID_BLOCK_TO_DMA,
|
|
||||||
READ_ID_BLOCK_TO_DMA_BYTE,
|
|
||||||
SEARCH_ADDRESS_MARK_DATA,
|
|
||||||
SEARCH_ADDRESS_MARK_DATA_FAILED,
|
|
||||||
READ_SECTOR_DATA,
|
|
||||||
READ_SECTOR_DATA_BYTE,
|
|
||||||
READ_TRACK_DATA,
|
|
||||||
READ_TRACK_DATA_BYTE,
|
|
||||||
WRITE_TRACK_DATA,
|
|
||||||
WRITE_BYTE,
|
|
||||||
WRITE_BYTE_DONE,
|
|
||||||
WRITE_SECTOR_PRE,
|
|
||||||
WRITE_SECTOR_PRE_BYTE,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pll_t {
|
|
||||||
UINT16 counter;
|
|
||||||
UINT16 increment;
|
|
||||||
UINT16 transition_time;
|
|
||||||
UINT8 history;
|
|
||||||
UINT8 slot;
|
|
||||||
UINT8 phase_add, phase_sub, freq_add, freq_sub;
|
|
||||||
attotime ctime;
|
|
||||||
|
|
||||||
attotime delays[42];
|
|
||||||
|
|
||||||
attotime write_start_time;
|
|
||||||
attotime write_buffer[32];
|
|
||||||
int write_position;
|
|
||||||
|
|
||||||
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 live_info {
|
|
||||||
enum { PT_NONE, PT_CRC_1, PT_CRC_2 };
|
|
||||||
|
|
||||||
attotime tm;
|
|
||||||
int state, next_state;
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
S_BUSY = 0x01,
|
|
||||||
S_DRQ = 0x02,
|
|
||||||
S_IP = 0x02,
|
|
||||||
S_TR00 = 0x04,
|
|
||||||
S_LOST = 0x04,
|
|
||||||
S_CRC = 0x08,
|
|
||||||
S_RNF = 0x10,
|
|
||||||
S_HLD = 0x20,
|
|
||||||
S_SPIN = 0x20, // WD1770, WD1772
|
|
||||||
S_DDM = 0x20,
|
|
||||||
S_WF = 0x20, // WD1773
|
|
||||||
S_WP = 0x40,
|
|
||||||
S_NRDY = 0x80,
|
|
||||||
S_MON = 0x80 // WD1770, WD1772
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
I_RDY = 0x01,
|
|
||||||
I_NRDY = 0x02,
|
|
||||||
I_IDX = 0x04,
|
|
||||||
I_IMM = 0x08
|
|
||||||
};
|
|
||||||
|
|
||||||
floppy_image_device *floppy;
|
|
||||||
|
|
||||||
emu_timer *t_gen, *t_cmd, *t_track, *t_sector;
|
|
||||||
|
|
||||||
bool dden, status_type_1, intrq, drq, hld, hlt, enp;
|
|
||||||
int main_state, sub_state;
|
|
||||||
UINT8 command, track, sector, data, status, intrq_cond;
|
|
||||||
int last_dir;
|
|
||||||
|
|
||||||
int counter, motor_timeout, sector_size;
|
|
||||||
|
|
||||||
int cmd_buffer, track_buffer, sector_buffer;
|
|
||||||
|
|
||||||
live_info cur_live, checkpoint_live;
|
|
||||||
line_cb intrq_cb, drq_cb, hld_cb, enp_cb;
|
|
||||||
|
|
||||||
static astring tts(attotime t);
|
|
||||||
astring ttsn();
|
|
||||||
|
|
||||||
void delay_cycles(emu_timer *tm, int cycles);
|
|
||||||
|
|
||||||
// Device timer subfunctions
|
|
||||||
void do_cmd_w();
|
|
||||||
void do_track_w();
|
|
||||||
void do_sector_w();
|
|
||||||
void do_generic();
|
|
||||||
|
|
||||||
|
|
||||||
// Main-state handling functions
|
|
||||||
void seek_start(int state);
|
|
||||||
void seek_continue();
|
|
||||||
|
|
||||||
void read_sector_start();
|
|
||||||
void read_sector_continue();
|
|
||||||
|
|
||||||
void read_track_start();
|
|
||||||
void read_track_continue();
|
|
||||||
|
|
||||||
void read_id_start();
|
|
||||||
void read_id_continue();
|
|
||||||
|
|
||||||
void write_track_start();
|
|
||||||
void write_track_continue();
|
|
||||||
|
|
||||||
void write_sector_start();
|
|
||||||
void write_sector_continue();
|
|
||||||
|
|
||||||
void interrupt_start();
|
|
||||||
|
|
||||||
void general_continue();
|
|
||||||
void command_end();
|
|
||||||
|
|
||||||
void spinup();
|
|
||||||
void index_callback(floppy_image_device *floppy, int state);
|
|
||||||
bool sector_matches() const;
|
|
||||||
bool is_ready();
|
|
||||||
|
|
||||||
void live_start(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);
|
|
||||||
bool read_one_bit(attotime limit);
|
|
||||||
bool write_one_bit(attotime limit);
|
|
||||||
|
|
||||||
void live_write_raw(UINT16 raw);
|
|
||||||
void live_write_mfm(UINT8 mfm);
|
|
||||||
|
|
||||||
void drop_drq();
|
|
||||||
void set_drq();
|
|
||||||
};
|
|
||||||
|
|
||||||
class fd1771_t : public wd177x_t {
|
|
||||||
public:
|
|
||||||
fd1771_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool has_ready() const { return true; }
|
|
||||||
virtual bool has_motor() const { return false; }
|
|
||||||
virtual bool has_head_load() const { return true; }
|
|
||||||
virtual bool has_side_check() const { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class fd1793_t : public wd177x_t {
|
|
||||||
public:
|
|
||||||
fd1793_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool has_ready() const { return true; }
|
|
||||||
virtual bool has_motor() const { return false; }
|
|
||||||
virtual bool has_head_load() const { return true; }
|
|
||||||
virtual bool has_side_check() const { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class fd1797_t : public wd177x_t {
|
|
||||||
public:
|
|
||||||
fd1797_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool has_ready() const { return true; }
|
|
||||||
virtual bool has_motor() const { return false; }
|
|
||||||
virtual bool has_head_load() const { return true; }
|
|
||||||
virtual bool has_side_select() const { return true; }
|
|
||||||
virtual bool has_sector_length_select() const { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class wd2793_t : public wd177x_t {
|
|
||||||
public:
|
|
||||||
wd2793_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool has_ready() const { return true; }
|
|
||||||
virtual bool has_motor() const { return false; }
|
|
||||||
virtual bool has_head_load() const { return true; }
|
|
||||||
virtual bool has_side_check() const { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class wd2797_t : public wd177x_t {
|
|
||||||
public:
|
|
||||||
wd2797_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool has_ready() const { return true; }
|
|
||||||
virtual bool has_motor() const { return false; }
|
|
||||||
virtual bool has_head_load() const { return true; }
|
|
||||||
virtual bool has_side_select() const { return true; }
|
|
||||||
virtual bool has_sector_length_select() const { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class wd1770_t : public wd177x_t {
|
|
||||||
public:
|
|
||||||
wd1770_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool has_motor() const { return true; }
|
|
||||||
virtual bool has_precompensation() const { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class wd1772_t : public wd177x_t {
|
|
||||||
public:
|
|
||||||
wd1772_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool has_motor() const { return true; }
|
|
||||||
virtual bool has_precompensation() const { return true; }
|
|
||||||
virtual int step_time(int mode) const;
|
|
||||||
virtual int settle_time() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class wd1773_t : public wd177x_t {
|
|
||||||
public:
|
|
||||||
wd1773_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool has_motor() const { return false; }
|
|
||||||
virtual bool has_head_load() const { return true; }
|
|
||||||
virtual bool has_side_check() const { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
extern const device_type FD1771x;
|
|
||||||
extern const device_type FD1793x;
|
|
||||||
extern const device_type FD1797x;
|
|
||||||
extern const device_type WD2793x;
|
|
||||||
extern const device_type WD2797x;
|
|
||||||
extern const device_type WD1770x;
|
|
||||||
extern const device_type WD1772x;
|
|
||||||
extern const device_type WD1773x;
|
|
||||||
|
|
||||||
#endif
|
|
@ -526,7 +526,6 @@ $(MESSOBJ)/shared.a: \
|
|||||||
$(MESS_MACHINE)/mos6530.o \
|
$(MESS_MACHINE)/mos6530.o \
|
||||||
$(MESS_MACHINE)/s100.o \
|
$(MESS_MACHINE)/s100.o \
|
||||||
$(MESS_MACHINE)/serial.o \
|
$(MESS_MACHINE)/serial.o \
|
||||||
$(MESS_MACHINE)/upd765.o \
|
|
||||||
$(MESS_MACHINE)/ncr5380.o \
|
$(MESS_MACHINE)/ncr5380.o \
|
||||||
$(MESS_MACHINE)/ncr5390.o \
|
$(MESS_MACHINE)/ncr5390.o \
|
||||||
$(MESS_MACHINE)/pc_kbdc.o \
|
$(MESS_MACHINE)/pc_kbdc.o \
|
||||||
@ -554,7 +553,6 @@ $(MESSOBJ)/shared.a: \
|
|||||||
$(MESS_MACHINE)/dp8390.o \
|
$(MESS_MACHINE)/dp8390.o \
|
||||||
$(MESS_MACHINE)/ne1000.o \
|
$(MESS_MACHINE)/ne1000.o \
|
||||||
$(MESS_MACHINE)/ne2000.o \
|
$(MESS_MACHINE)/ne2000.o \
|
||||||
$(MESS_MACHINE)/wd1772.o \
|
|
||||||
$(MESS_MACHINE)/3c503.o \
|
$(MESS_MACHINE)/3c503.o \
|
||||||
$(MESS_FORMATS)/z80bin.o \
|
$(MESS_FORMATS)/z80bin.o \
|
||||||
$(MESS_MACHINE)/mb8795.o \
|
$(MESS_MACHINE)/mb8795.o \
|
||||||
|
Loading…
Reference in New Issue
Block a user