OXYGENHUB
◆ main openmsx / src / fdc / SVIFDC.cc
3.0 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "SVIFDC.hh"
2
3
#include "serialize.hh"
4
5
// Floppy disk controller FD1793
6
//
7
// 30H         Command to FDC
8
// 30H         Status from FDC
9
// 31H         Track register
10
// 32H         Sector register
11
// 33H         Data register
12
//
13
// 34H         Address of INTRQ and DRQ
14
// 10000000B   Interrupt request bit
15
// 01000000B   Data request bit
16
//
17
// 34H         Address of disk select and motor control
18
// 00000001B   Select disk 0 bit
19
// 00000010B   Select disk 1 bit
20
// 00000100B   Disk 0 motor on bit
21
// 00001000B   Disk 1 motor on bit
22
//
23
// 38H         Address of density select flag
24
// 00000000B   Density MFM bit
25
// 00000001B   Density FM bit
26
// 00000010B   Select second side
27
28
namespace openmsx {
29
30
SVIFDC::SVIFDC(DeviceConfig& config)
31
	: WD2793BasedFDC(config, "", false) // doesn't require a <rom>
32
{
33
}
34
35
byte SVIFDC::readIO(uint16_t port, EmuTime time)
36
{
37
	switch (port & 0x07) {
38
	case 0:
39
		return controller.getStatusReg(time);
40
	case 1:
41
		return controller.getTrackReg(time);
42
	case 2:
43
		return controller.getSectorReg(time);
44
	case 3:
45
		return controller.getDataReg(time);
46
	case 4:
47
		return (controller.getIRQ (time) ? 0x80 : 0x00) |
48
		       (controller.getDTRQ(time) ? 0x40 : 0x00);
49
	}
50
	return 255;
51
}
52
53
byte SVIFDC::peekIO(uint16_t port, EmuTime time) const
54
{
55
	switch (port & 0x07) {
56
	case 0:
57
		return controller.peekStatusReg(time);
58
	case 1:
59
		return controller.peekTrackReg(time);
60
	case 2:
61
		return controller.peekSectorReg(time);
62
	case 3:
63
		return controller.peekDataReg(time);
64
	case 4:
65
		return (controller.peekIRQ (time) ? 0x80 : 0x00) |
66
		       (controller.peekDTRQ(time) ? 0x40 : 0x00);
67
	}
68
	return 255;
69
}
70
71
void SVIFDC::writeIO(uint16_t port, byte value, EmuTime time)
72
{
73
	switch (port & 0x0F) {
74
	case 0:
75
		controller.setCommandReg(value, time);
76
		break;
77
	case 1:
78
		controller.setTrackReg(value, time);
79
		break;
80
	case 2:
81
		controller.setSectorReg(value, time);
82
		break;
83
	case 3:
84
		controller.setDataReg(value, time);
85
		break;
86
	case 4: {
87
		// bit 0:  drive select A
88
		// bit 1:  drive select B
89
		// bit 2:  motor on drive A
90
		// bit 3:  motor on drive B
91
		auto [drive, motor] = [&] -> std::pair<DriveMultiplexer::Drive, bool> {
92
			switch (value & 0x03) {
93
			case 1:
94
				return {DriveMultiplexer::Drive::A, value & 0x04};
95
			case 2:
96
				return {DriveMultiplexer::Drive::B, value & 0x08};
97
			default:
98
				// No drive selected or two drives at same time
99
				// In a real machine you must take care to do not select more
100
				// than one drive at the same time (you could get data
101
				// collision).
102
				return {DriveMultiplexer::Drive::NONE, false};
103
			}
104
		}();
105
		multiplexer.selectDrive(drive, time);
106
		multiplexer.setMotor(motor, time);
107
		break;
108
	}
109
	case 8:
110
		// bit 0:  density flag (1=single, 0=double)
111
		// bit 1:  side select
112
		// TODO density flag not yet supported
113
		multiplexer.setSide((value & 0x02) != 0);
114
		break;
115
	}
116
}
117
118
template<typename Archive>
119
void SVIFDC::serialize(Archive& ar, unsigned /*version*/)
120
{
121
	ar.template serializeBase<WD2793BasedFDC>(*this);
122
}
123
INSTANTIATE_SERIALIZE_METHODS(SVIFDC);
124
REGISTER_MSXDEVICE(SVIFDC, "SVI-328 FDC");
125
126
} // namespace openmsx