summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/isa/myb3k_fdc.cpp
blob: b23fe5258bc3d1e183108bd3a0a2284603b7c4a2 (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
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
// license:BSD-3-Clause
// copyright-holders:Joakim Larsson Edstrom
/**********************************************************************

    ISA 8 bit Floppy Disk Controller for Matsushita MyBrain 3000,
    Panasonic JB-3000 and Ericsson Step/One

    FDC4710 - 5.25" FDD4730
     - 1-2 x SSDD 40 tracks, 8 sectors/track, 512 bytes/sector 160KB

    FDC4711 - 5.25" FDD4731/FDD4732 (FDD4732 has external power needed for drive 3-4)
     - 1-4 x DSDD 80 tracks, 8 sectors/track, 512 bytes/sector 720KB

    FDC4712 - 8" FDD4733
     - 1-2 x DSDD 154 tracks, 8 sector/track, 1024 bytes/sector 1232KB

    Step/One service manuals: http://nivelleringslikaren.eu/stepone/

   TODO:
   - Verify FDC4710 as soon as we find a 160Kb floppy image
   - Add FDC4712 8" as soon as we get a visual or schematics on it
   - Reduce code duplication by introducing a base class, once all are emulated
   - Put these into global ISA8 collection

********************************************************************************/

#include "emu.h"
#include "myb3k_fdc.h"
#include "imagedev/flopdrv.h"
#include "formats/pc_dsk.h"
#include "formats/imd_dsk.h"

//#define LOG_GENERAL (1U << 0) //defined in logmacro.h already
#define LOG_READ    (1U << 1)
#define LOG_CMD     (1U << 2)

//#define VERBOSE (LOG_GENERAL | LOG_CMD)
//#define LOG_OUTPUT_STREAM std::cout

#include "logmacro.h"

#define LOGR(...)   LOGMASKED(LOG_READ, __VA_ARGS__)
#define LOGCMD(...) LOGMASKED(LOG_CMD,  __VA_ARGS__)

#ifdef _MSC_VER
#define FUNCNAME __func__
#else
#define FUNCNAME __PRETTY_FUNCTION__
#endif

DEFINE_DEVICE_TYPE(ISA8_MYB3K_FDC4710, isa8_myb3k_fdc4710_device, "isa8_myb3k_fdc4710", "FDC4710 SSDD Floppy Disk Controller")
DEFINE_DEVICE_TYPE(ISA8_MYB3K_FDC4711, isa8_myb3k_fdc4711_device, "isa8_myb3k_fdc4711", "FDC4711 DSDD Floppy Disk Controller")

DEVICE_ADDRESS_MAP_START(map, 8, isa8_myb3k_fdc4710_device)
//  AM_RANGE(0x00, 0x03) AM_DEVREADWRITE("fdc", mb8876_device, read, write) AM_MIRROR(0x500)
	AM_RANGE(0x00, 0x03) AM_READ(myb3k_inv_fdc_data_r) AM_WRITE(myb3k_inv_fdc_data_w) AM_MIRROR(0x500)
	AM_RANGE(0x04, 0x04) AM_WRITE(myb3k_fdc_command) AM_MIRROR(0x500)
	AM_RANGE(0x05, 0x05) AM_READ(myb3k_fdc_status) AM_MIRROR(0x500)
ADDRESS_MAP_END

DEVICE_ADDRESS_MAP_START(map, 8, isa8_myb3k_fdc4711_device)
//  AM_RANGE(0x00, 0x03) AM_DEVREADWRITE("fdc", fd1791_device, read, write) AM_MIRROR(0x500)
	AM_RANGE(0x00, 0x03) AM_READ(myb3k_inv_fdc_data_r) AM_WRITE(myb3k_inv_fdc_data_w) AM_MIRROR(0x500)
	AM_RANGE(0x04, 0x04) AM_WRITE(myb3k_fdc_command) AM_MIRROR(0x500)
	AM_RANGE(0x05, 0x05) AM_READ(myb3k_fdc_status) AM_MIRROR(0x500)
ADDRESS_MAP_END

FLOPPY_FORMATS_MEMBER( isa8_myb3k_fdc4710_device::myb3k_floppy_formats )
	FLOPPY_IMD_FORMAT
FLOPPY_FORMATS_END

FLOPPY_FORMATS_MEMBER( isa8_myb3k_fdc4711_device::myb3k_floppy_formats )
	FLOPPY_PC_FORMAT,
	FLOPPY_IMD_FORMAT
FLOPPY_FORMATS_END

static SLOT_INTERFACE_START( myb3k_sd_floppies )
	SLOT_INTERFACE( "525sd", FLOPPY_525_SD )
SLOT_INTERFACE_END

static SLOT_INTERFACE_START( myb3k_qd_floppies )
	SLOT_INTERFACE( "525qd", FLOPPY_525_QD )
SLOT_INTERFACE_END

#if 0
static SLOT_INTERFACE_START( myb3k_8inch_floppies )
	SLOT_INTERFACE( "8dsdd", FLOPPY_8_DSDD )
SLOT_INTERFACE_END
#endif

//-------------------------------------------------
//  device_add_mconfig - add device configuration
//-------------------------------------------------
/*  */
MACHINE_CONFIG_START(isa8_myb3k_fdc4710_device::device_add_mconfig)
	MCFG_DEVICE_ADD("fdc", MB8876, XTAL_15_9744MHz / 8) /* From StepOne schematics */
	MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(isa8_myb3k_fdc4710_device, irq_w))
	MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(isa8_myb3k_fdc4710_device, drq_w))
	MCFG_FLOPPY_DRIVE_ADD("fdc:0", myb3k_sd_floppies, "525sd", isa8_myb3k_fdc4710_device::myb3k_floppy_formats)
	MCFG_FLOPPY_DRIVE_ADD("fdc:1", myb3k_sd_floppies, "525sd", isa8_myb3k_fdc4710_device::myb3k_floppy_formats)
MACHINE_CONFIG_END

/* Main difference from fdc4710 is that a Hitachi HA16632AP has replaced the descrete VFO enabling 720Kb disks */
MACHINE_CONFIG_START(isa8_myb3k_fdc4711_device::device_add_mconfig)
	MCFG_DEVICE_ADD("fdc", FD1791, XTAL_15_9744MHz / 16)
	MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(isa8_myb3k_fdc4711_device, irq_w))
	MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(isa8_myb3k_fdc4711_device, drq_w))
	MCFG_FLOPPY_DRIVE_ADD("fdc:0", myb3k_qd_floppies, "525qd", isa8_myb3k_fdc4711_device::myb3k_floppy_formats)
	MCFG_FLOPPY_DRIVE_ADD("fdc:1", myb3k_qd_floppies, "525qd", isa8_myb3k_fdc4711_device::myb3k_floppy_formats)
	MCFG_FLOPPY_DRIVE_ADD("fdc:2", myb3k_qd_floppies, "525qd", isa8_myb3k_fdc4711_device::myb3k_floppy_formats)
	MCFG_FLOPPY_DRIVE_ADD("fdc:3", myb3k_qd_floppies, "525qd", isa8_myb3k_fdc4711_device::myb3k_floppy_formats)
MACHINE_CONFIG_END

#if 0
MACHINE_CONFIG_START(isa8_myb3k_fdc4712_device::device_add_mconfig)
	MCFG_DEVICE_ADD("fdc", FD1791, XTAL_15_9744MHz / 8)
	MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(isa8_myb3k_fdc4712_device, irq_w))
	MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(isa8_myb3k_fdc4712_device, drq_w))
	MCFG_FLOPPY_DRIVE_ADD("fdc:0", myb3k_8inch_floppies, "8dsdd", isa8_myb3k_fdc4712_device::myb3k_floppy_formats)
	MCFG_FLOPPY_DRIVE_ADD("fdc:1", myb3k_8inch_floppies, "8dsdd", isa8_myb3k_fdc4712_device::myb3k_floppy_formats)
MACHINE_CONFIG_END
#endif

//**************************************************************************
//  LIVE DEVICES
//**************************************************************************
isa8_myb3k_fdc4710_device::isa8_myb3k_fdc4710_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
	device_t(mconfig, type, tag, owner, clock)
	, device_isa8_card_interface(mconfig, *this)
	, m_fdc(*this, "fdc")
	, m_fdd0(*this, "fdc:0")
	, m_fdd1(*this, "fdc:1")
{
}

isa8_myb3k_fdc4710_device::isa8_myb3k_fdc4710_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : isa8_myb3k_fdc4710_device(mconfig, ISA8_MYB3K_FDC4710, tag, owner, clock)
{
}

isa8_myb3k_fdc4711_device::isa8_myb3k_fdc4711_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
	device_t(mconfig, type, tag, owner, clock)
	, device_isa8_card_interface(mconfig, *this)
	, m_fdc(*this, "fdc")
	, m_fdd0(*this, "fdc:0")
	, m_fdd1(*this, "fdc:1")
	, m_fdd2(*this, "fdc:2")
	, m_fdd3(*this, "fdc:3")
{
}

isa8_myb3k_fdc4711_device::isa8_myb3k_fdc4711_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : isa8_myb3k_fdc4711_device(mconfig, ISA8_MYB3K_FDC4711, tag, owner, clock)
{
}

//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------
void isa8_myb3k_fdc4710_device::device_start()
{
	LOG("%s\n", FUNCNAME);

	set_isa_device();
	m_isa->set_dma_channel(2, this, true);
	m_isa->install_device(0x020, 0x027, *this, &isa8_myb3k_fdc4710_device::map, 8);
}

void isa8_myb3k_fdc4711_device::device_start()
{
	LOG("%s\n", FUNCNAME);

	set_isa_device();
	m_isa->install_device(0x020, 0x027, *this, &isa8_myb3k_fdc4711_device::map, 8);
	m_isa->set_dma_channel(2, this, true);
}

//-------------------------------------------------
//  device_reset - device-specific reset
//-------------------------------------------------
void isa8_myb3k_fdc4710_device::device_reset()
{
	LOG("%s\n", FUNCNAME);
}

void isa8_myb3k_fdc4711_device::device_reset()
{
	LOG("%s\n", FUNCNAME);
}

//-------------------------------------------------
//  irq_w - signal interrupt request to ISA bus
//-------------------------------------------------
WRITE_LINE_MEMBER( isa8_myb3k_fdc4710_device::irq_w )
{
	LOG("%s: %d\n", FUNCNAME, state);
	m_isa->irq6_w(state ? ASSERT_LINE : CLEAR_LINE);
}

WRITE_LINE_MEMBER( isa8_myb3k_fdc4711_device::irq_w )
{
	LOG("%s: %d\n", FUNCNAME, state);
	m_isa->irq6_w(state ? ASSERT_LINE : CLEAR_LINE);
}

//-------------------------------------------------
//  drq_w - signal dma request to ISA bus
//-------------------------------------------------
WRITE_LINE_MEMBER( isa8_myb3k_fdc4710_device::drq_w )
{
	LOG("%s: %d\n", FUNCNAME, state);
	m_isa->drq2_w(state ? ASSERT_LINE : CLEAR_LINE);
}

WRITE_LINE_MEMBER( isa8_myb3k_fdc4711_device::drq_w )
{
	LOG("%s: %d\n", FUNCNAME, state);
	m_isa->drq2_w(state ? ASSERT_LINE : CLEAR_LINE);
}

//-------------------------------------------------
//  dack_r - return FDC data trough DMA
//-------------------------------------------------
uint8_t isa8_myb3k_fdc4710_device::dack_r(int line)
{
	return ~(m_fdc->data_r());
}

uint8_t isa8_myb3k_fdc4711_device::dack_r(int line)
{
	return ~(m_fdc->data_r());
}

//-------------------------------------------------
//  dack_w - write DMA data to FDC
//-------------------------------------------------
void isa8_myb3k_fdc4710_device::dack_w(int line, uint8_t data)
{
	return m_fdc->data_w(data);
}

void isa8_myb3k_fdc4711_device::dack_w(int line, uint8_t data)
{
	return m_fdc->data_w(data);
}

#if 0 // eop/tc is used to for logic around multi sector transfers
void isa8_myb3k_fdc4710_device::eop_w(int state)
{
	m_fdc->tc_w(state == ASSERT_LINE);
}

void isa8_myb3k_fdc4711_device::eop_w(int state)
{
	m_fdc->tc_w(state == ASSERT_LINE);
}
#endif

//--------------------------------------------------------
//  myb3k_inv_fdc_data_r - a LS240 inverts databus for FDC
//--------------------------------------------------------
READ8_MEMBER( isa8_myb3k_fdc4710_device::myb3k_inv_fdc_data_r )
{
	uint8_t tmp = m_fdc->read(space, offset);
	LOGR("%s: %02x -> %02x\n", FUNCNAME, tmp, (~tmp) & 0xff);
	return ~tmp;
}

READ8_MEMBER( isa8_myb3k_fdc4711_device::myb3k_inv_fdc_data_r )
{
	uint8_t tmp = m_fdc->read(space, offset);
	LOGR("%s: %02x -> %02x\n", FUNCNAME, tmp, (~tmp) & 0xff);
	return ~tmp;
}

//--------------------------------------------------------
//  myb3k_inv_fdc_data_w - a LS240 inverts databus for FDC
//--------------------------------------------------------
WRITE8_MEMBER( isa8_myb3k_fdc4710_device::myb3k_inv_fdc_data_w )
{
	LOG("%s: %02x -> %02x\n", FUNCNAME, data, (~data) & 0xff);
	m_fdc->write(space, offset, (~data) & 0xff);
}

WRITE8_MEMBER( isa8_myb3k_fdc4711_device::myb3k_inv_fdc_data_w )
{
	LOG("%s: %02x -> %02x\n", FUNCNAME, data, (~data) & 0xff);
	m_fdc->write(space, offset, (~data) & 0xff);
}

//-------------------------------------------------
//  myb3k_fdc_command - descrete fdc card features
//-------------------------------------------------
WRITE8_MEMBER( isa8_myb3k_fdc4710_device::myb3k_fdc_command )
{
	data = ~data;
	LOG("%s: %02x\n", FUNCNAME, data);
	LOGCMD(" - Drive %d\n", ~data & FDC_DRIVE_SEL);
	LOGCMD(" - Side  %d\n", (data & FDC_SIDE_SEL) ? 0 : 1);
	LOGCMD(" - Motor %s\n", (data & FDC_MOTOR_ON) ? "OFF" : "ON");
	LOGCMD(" - Density %s\n", (data & FDC_DDEN) ? "FM" : "MFM");

	floppy_image_device *floppy = nullptr;

	switch(~data & FDC_DRIVE_SEL) // Y0-Y3 on a '139 maps to drive 4 to 1 respectively
	{
	case 0:floppy = m_fdd0->get_device(); break;
	case 1:floppy = m_fdd1->get_device(); break;
	}

	if (floppy)
	{
		LOGCMD(" - Floppy found\n");
		m_fdc->set_floppy(floppy);
		floppy->ss_w((data & FDC_SIDE_SEL) ? 0 : 1);
		floppy->mon_w((data & FDC_MOTOR_ON) ? 1 : 0); // Active low and inverter on incomming data line
	}
	else
	{
		LOGCMD(" - Floppy not found\n");
	}
	m_fdc->dden_w((data & FDC_DDEN) ? 1 : 0); // active low == MFM
}

WRITE8_MEMBER( isa8_myb3k_fdc4711_device::myb3k_fdc_command )
{
	data = ~data;
	LOG("%s: %02x\n", FUNCNAME, data);
	LOGCMD(" - Drive %d\n", ~data & FDC_DRIVE_SEL);
	LOGCMD(" - Side  %d\n", (data & FDC_SIDE_SEL) ? 0 : 1);
	LOGCMD(" - Motor %s\n", (data & FDC_MOTOR_ON) ? "OFF" : "ON");
	LOGCMD(" - Density %s\n", (data & FDC_DDEN) ? "FM" : "MFM");

	floppy_image_device *floppy = nullptr;

	switch(~data & FDC_DRIVE_SEL) // Y0-Y3 on a '139 maps to drive 4 to 1 respectively
	{
	case 0:floppy = m_fdd0->get_device(); break;
	case 1:floppy = m_fdd1->get_device(); break;
	case 2:floppy = m_fdd2->get_device(); break;
	case 3:floppy = m_fdd3->get_device(); break;
	}

	if (floppy)
	{
		LOGCMD(" - Floppy found\n");
		m_fdc->set_floppy(floppy);
		floppy->ss_w((data & FDC_SIDE_SEL) ? 0 : 1);
		floppy->mon_w((data & FDC_MOTOR_ON) ? 1 : 0); // Active low and inverter on incomming data line
	}
	else
	{
		LOGCMD(" - Floppy not found\n");
	}
	m_fdc->dden_w((data & FDC_DDEN) ? 1 : 0); // active low == MFM
}

//-------------------------------------------------
//  myb3k_fdc_status - descrete fdc card status
//-------------------------------------------------
#define FDC_MSM_END_IR 0x01
READ8_MEMBER( isa8_myb3k_fdc4710_device::myb3k_fdc_status )
{
	LOG("%s\n", FUNCNAME);
	// TODO: return the multi sector mode interrupt status
	return 0x00;
}

READ8_MEMBER( isa8_myb3k_fdc4711_device::myb3k_fdc_status )
{
	LOG("%s\n", FUNCNAME);
	// TODO: return the multi sector mode interrupt status
	return 0x00;
}