OXYGENHUB
◆ main openmsx / src / fdc / MicrosolFDC.cc
2.9 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "MicrosolFDC.hh"
2
3
#include "DriveMultiplexer.hh"
4
#include "WD2793.hh"
5
6
#include "serialize.hh"
7
8
namespace openmsx {
9
10
MicrosolFDC::MicrosolFDC(DeviceConfig& config)
11
	: WD2793BasedFDC(config)
12
{
13
}
14
15
byte MicrosolFDC::readIO(uint16_t port, EmuTime time)
16
{
17
	switch (port & 0x07) {
18
	case 0:
19
		return controller.getStatusReg(time);
20
	case 1:
21
		return controller.getTrackReg(time);
22
	case 2:
23
		return controller.getSectorReg(time);
24
	case 3:
25
		return controller.getDataReg(time);
26
	case 4: {
27
		byte value = 0x7F;
28
		if (controller.getIRQ(time))  value |=  0x80;
29
		if (controller.getDTRQ(time)) value &= ~0x40;
30
		return value;
31
	}
32
	default:
33
		return 255;
34
	}
35
}
36
37
byte MicrosolFDC::peekIO(uint16_t port, EmuTime time) const
38
{
39
	switch (port & 0x07) {
40
	case 0:
41
		return controller.peekStatusReg(time);
42
	case 1:
43
		return controller.peekTrackReg(time);
44
	case 2:
45
		return controller.peekSectorReg(time);
46
	case 3:
47
		return controller.peekDataReg(time);
48
	case 4: {
49
		byte value = 0x7F;
50
		if (controller.peekIRQ(time))  value |=  0x80;
51
		if (controller.peekDTRQ(time)) value &= ~0x40;
52
		return value;
53
	}
54
	default:
55
		return 255;
56
	}
57
}
58
59
void MicrosolFDC::writeIO(uint16_t port, byte value, EmuTime time)
60
{
61
	switch (port & 0x07) {
62
	case 0:
63
		controller.setCommandReg(value, time);
64
		break;
65
	case 1:
66
		controller.setTrackReg(value, time);
67
		break;
68
	case 2:
69
		controller.setSectorReg(value, time);
70
		break;
71
	case 3:
72
		controller.setDataReg(value, time);
73
		break;
74
	case 4:
75
		// From Ricardo Bittencourt
76
		// bit 0:  drive select A
77
		// bit 1:  drive select B
78
		// bit 2:  drive select C
79
		// bit 3:  drive select D
80
		// bit 4:  side select
81
		// bit 5:  turn on motor
82
		// bit 6:  enable wait states
83
		// bit 7:  density: 0=single 1=double
84
		//
85
		// When you enable a drive select bit, the led on the
86
		// disk-drive turns on. Since this was used as user feedback,
87
		// in things such as "replace disk 1 when the led turns off"
88
		// we need to connect this to the OSD later on.
89
90
		// Set correct drive
91
		auto drive = [&] {
92
			switch (value & 0x0F) {
93
			case 1:
94
				return DriveMultiplexer::Drive::A;
95
			case 2:
96
				return DriveMultiplexer::Drive::B;
97
			case 4:
98
				return DriveMultiplexer::Drive::C;
99
			case 8:
100
				return DriveMultiplexer::Drive::D;
101
			default:
102
				// No drive selected or two drives at same time
103
				// The motor is enabled for all drives at the same time, so
104
				// in a real machine you must take care to do not select more
105
				// than one drive at the same time (you could get data
106
				// collision).
107
				return DriveMultiplexer::Drive::NONE;
108
			}
109
		}();
110
		multiplexer.selectDrive(drive, time);
111
		multiplexer.setSide((value & 0x10) != 0);
112
		multiplexer.setMotor((value & 0x20) != 0, time);
113
		break;
114
	}
115
}
116
117
118
template<typename Archive>
119
void MicrosolFDC::serialize(Archive& ar, unsigned /*version*/)
120
{
121
	ar.template serializeBase<WD2793BasedFDC>(*this);
122
}
123
INSTANTIATE_SERIALIZE_METHODS(MicrosolFDC);
124
REGISTER_MSXDEVICE(MicrosolFDC, "MicrosolFDC");
125
126
} // namespace openmsx