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
|