summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/machine/smc92x4.h
blob: 0d942fd87731f2cdbce7a23dcb171413648facd7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/* Interface */

#ifndef __SMC92X4_H__
#define __SMC92X4_H__

#include "ti99/ti99_hd.h"
#include "imagedev/flopdrv.h"
#include "formats/imageutl.h"
#include "imagedev/harddriv.h"
#include "harddisk.h"

#define INPUT_STATUS	0x00
#define OUTPUT_DMA_ADDR 0x01
#define OUTPUT_OUTPUT1	0x02
#define OUTPUT_OUTPUT2	0x03

#define MFMHD_TRACK00	0x80
#define MFMHD_SEEKCOMP	0x40
#define MFMHD_WRFAULT	0x20
#define MFMHD_READY	0x10
#define MFMHD_INDEX	0x08

#define BAD_SECTOR	0x1000
#define BAD_CRC		0x2000

extern const device_type SMC92X4;
/*
    Definition of bits in the Disk-Status register
*/
#define DS_ECCERR	0x80		/* ECC error */
#define DS_INDEX	0x40		/* index point */
#define DS_SKCOM	0x20		/* seek complete */
#define DS_TRK00	0x10		/* track 0 */
#define DS_UDEF		0x08		/* user-defined */
#define DS_WRPROT	0x04		/* write protect */
#define DS_READY	0x02		/* drive ready bit */
#define DS_WRFAULT	0x01		/* write fault */

struct smc92x4_interface
{
	// Disk format support. This flag allows to choose between the full
	// FM/MFM format and an abbreviated track layout. The difference results
	// from legal variations of the layout. This is not part of
	// the smc92x4 specification, but it allows to keep the image format
	// simple without too much case checking. Should be removed as soon as
	// the respective disk formats support the full format.
	int full_track_layout;

	// Interrupt line. To be connected with the controller PCB.
	devcb_write_line out_intrq;

	// DMA in progress line. To be connected with the controller PCB.
	devcb_write_line out_dip;

	// Auxiliary Bus. These 8 lines need to be connected to external latches
	// and to a counter circuitry which works together with the external RAM.
	// We use the S0/S1 lines as address lines.
	devcb_write8	out_auxbus;

	// Auxiliary Bus. This is only used for S0=S1=0.
	devcb_read8 	in_auxbus;

	// Callback to read the contents of the external RAM via the data bus.
	// Note that the address must be set and automatically increased
	// by external circuitry.
	devcb_read8 	dma_read;

	// Callback to write the contents of the external RAM via the data bus.
	// Note that the address must be set and automatically increased
	// by external circuitry. */
	devcb_write8	dma_write;

};


class smc92x4_device : public device_t
{
public:
	smc92x4_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);

	DECLARE_READ8_MEMBER( read );
	DECLARE_WRITE8_MEMBER( write );

	// Used to turn off the delays.
	void set_timing(bool realistic);

	// Used to reconfigure the drive connections. Drive selection is done
	// using the select lines and maybe also the user-programmable outputs.
	void connect_drive(device_t *drive);

	void reset();

protected:
	void device_start(void);
	void device_reset(void);

private:
	devcb_resolved_write_line	m_out_intrq;	// INT line
	devcb_resolved_write_line	m_out_dip;		// DMA in progress line
	devcb_resolved_write8		m_out_auxbus;	// AB0-7 lines (using S0,S1 as address)
	devcb_resolved_read8		m_in_auxbus;	// AB0-7 lines (S0=S1=0)
	devcb_resolved_read8		m_in_dma;		// DMA read access to the cache buffer
	devcb_resolved_write8		m_out_dma;		// DMA write access to the cache buffer

	UINT8 m_output1;		// internal register "output1"
	UINT8 m_output2;		// internal register "output2"

	void	set_dip(line_state value);
	int 	image_is_single_density();
	bool	in_single_density_mode();
	void	copyid(chrn_id id1, chrn_id_hd *id2);
	void	set_interrupt();
	void	clear_interrupt();
	void	set_command_done(int flags);
	void	set_command_done();
	void	set_dma_address(int pos2316, int pos1508, int pos0700);
	void	dma_add_offset(int offset);
	void	sync_status_in();
	void	sync_latches_out();
	void	timed_sector_read_request();
	void	timed_sector_write_request();
	void	timed_track_request();
	void	timed_seek_request();
	void	device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
	UINT8	cylinder_to_ident(int cylinder);
	int		ident_to_cylinder(UINT8 ident);
	void	update_id_regs(chrn_id_hd id);
	void	read_id_field(int *steps, int *direction, chrn_id_hd *id);
	int		verify(chrn_id_hd *id, bool check_sector);
	void	data_transfer_read(chrn_id_hd id, int transfer_enable);
	void	data_transfer_write(chrn_id_hd id, int deldata, int redcur, int precomp, bool write_long);
	void	read_write_sectors();
	void	read_sectors_continue();
	void	write_sectors_continue();

	void	restore_drive();
	void	restore_continue();

	void	step_in_out();
	void	step_continue();

	void	poll_drives();

	void	drive_select(int driveparm);

	void	seek_read_id();
	void	seek_read_id_continue();

	void	format_track();
	void	format_track_continue();
	void	format_floppy_track(int flags);
	void	format_harddisk_track(int flags);

	void	read_track();
	void	read_track_continue();
	void	read_floppy_track(bool transfer_only_ids);
	void	read_harddisk_track(bool transfer_only_ids);

	void	process_after_callback();
	void	process_command(UINT8 opcode);

	int	m_selected_drive_type;
	// We need to store the types, although this is not the case in the
	// real hardware. The reason is that poll_drives wants to select the
	// drives without knowing their kinds. In reality this does not matter,
	// since we only check for the seek_complete line, but in our case,
	// floppy and harddrive are pretty different, and we need to know which
	// one to check.
	int	m_types[4];
	int	m_head_load_delay_enable;
	int	m_register_pointer;

	UINT8 m_register_r[12];
	UINT8 m_register_w[12];

	/* timers to delay execution/completion of commands */
	emu_timer *m_timer_data, *m_timer_rs, *m_timer_ws, *m_timer_seek, *m_timer_track;

	/* Flag which determines whether to use realistic timing. */
	bool m_use_real_timing;

	/* Required to store the current iteration within restore. */
	int m_seek_count;

	/* Recent command. */
	UINT8 m_command;

	/* Stores the step direction. */
	int m_step_direction;

	/* Stores the buffered flag. */
	bool m_buffered;

	/* Stores the recent id field. */
	chrn_id_hd m_recent_id;

	/* Indicates whether an ID has been found. */
	bool m_found_id;

	/* Indicates whether we are already past the seek_id phase in read/write sector. */
	bool m_after_seek;

	/* Determines whether the command will be continued. */
	bool m_to_be_continued;

	bool m_full_track_layout;

	// Link to attached drive (hard / floppy disk)
	// Hard disks must be instances of mfmhd_device; floppy disks are the common drives.
	// We expect the embedding board to replace the drive according to the
	// select lines.
	device_t	*m_drive;
};

#define MCFG_SMC92X4_ADD(_tag, _intrf) \
	MCFG_DEVICE_ADD(_tag, SMC92X4, 0) \
	MCFG_DEVICE_CONFIG(_intrf)

#endif