openMSX
CanonFDC.cc
Go to the documentation of this file.
1 #include "CanonFDC.hh"
2 #include "CacheLine.hh"
3 #include "serialize.hh"
4 
5 // Technical info and discussion on:
6 // https://www.msx.org/forum/msx-talk/hardware/canon-v-30f-msx2?page=8
7 //
8 // 0x7FF8: MB8877A command register (W) / Status register (R)
9 // 0x7FF9: MB8877A track register (R/W)
10 // 0x7FFA: MB8877A sector register (R/W)
11 // 0x7FFB: MB8877A data register (R/W)
12 // 0x7FFC: drive control
13 // b1,b0: (R/W) drive select (0 = drive 0, 1 = drive 1, 3 = deselect drive)
14 // b2: (R/W) side select (0 = side 0, 1 = side 1)
15 // b3: (R/W) motor on (1 = motor on)
16 // b4: (R) disk changed (0 = changed)
17 // b5 (R) some sort of ready (1 = ready)
18 // b6 (R) DRQ (1 = DRQ)
19 // b7 (R) IRQ (1 = IRQ)
20 // Hardware registers are also visible in page 2 (0xBFF8-0xBFFC).
21 
22 namespace openmsx {
23 
25  : WD2793BasedFDC(config)
26 {
27 }
28 
29 void CanonFDC::reset(EmuTime::param time)
30 {
32  writeMem(0x3FFC, 0, time);
33 }
34 
35 byte CanonFDC::readMem(word address, EmuTime::param time)
36 {
37  switch (address & 0x3FFF) {
38  case 0x3FF8:
39  return controller.getStatusReg(time);
40  case 0x3FF9:
41  return controller.getTrackReg(time);
42  case 0x3FFA:
43  return controller.getSectorReg(time);
44  case 0x3FFB:
45  return controller.getDataReg(time);
46  case 0x3FFC: {
47  // At address 0x76F4 in the disk ROM bit 5 is checked. If this
48  // bit is 0, the code executes a delay loop. Not sure what that
49  // is for. Some kind of hardware debug feature??
50  byte value = 0x30 | controlReg;
51  if (controller.getIRQ(time)) value |= 0x40;
52  if (controller.getDTRQ(time)) value |= 0x80;
53  if (multiplexer.diskChanged()) value &= ~0x10;
54  return value;
55  }
56  default:
57  return CanonFDC::peekMem(address, time);
58  }
59 }
60 
61 byte CanonFDC::peekMem(word address, EmuTime::param time) const
62 {
63  switch (address & 0x3FFF) {
64  case 0x3FF8:
65  return controller.peekStatusReg(time);
66  case 0x3FF9:
67  return controller.peekTrackReg(time);
68  case 0x3FFA:
69  return controller.peekSectorReg(time);
70  case 0x3FFB:
71  return controller.peekDataReg(time);
72  case 0x3FFC: {
73  byte value = 0x30 | controlReg;
74  if (controller.peekIRQ(time)) value |= 0x40;
75  if (controller.peekDTRQ(time)) value |= 0x80;
76  if (multiplexer.peekDiskChanged()) value &= ~0x10;
77  return value;
78  }
79  default:
80  return MSXFDC::peekMem(address, time);
81  }
82 }
83 
84 const byte* CanonFDC::getReadCacheLine(word start) const
85 {
86  if ((start & 0x3FFF & CacheLine::HIGH) == (0x3FF0 & CacheLine::HIGH)) {
87  // FDC at 0x7FF8-0x7FFC and 0xBFF8-0xBFFC
88  return nullptr;
89  } else {
90  return MSXFDC::getReadCacheLine(start);
91  }
92 }
93 
94 void CanonFDC::writeMem(word address, byte value, EmuTime::param time)
95 {
96  switch (address & 0x3FFF) {
97  case 0x3FF8:
98  controller.setCommandReg(value, time);
99  break;
100  case 0x3FF9:
101  controller.setTrackReg(value, time);
102  break;
103  case 0x3FFA:
104  controller.setSectorReg(value, time);
105  break;
106  case 0x3FFB:
107  controller.setDataReg(value, time);
108  break;
109  case 0x3FFC: {
110  controlReg = value & 0x0F;
111  auto drive = [&] {
112  switch (value & 3) {
113  case 0: return DriveMultiplexer::DRIVE_A;
114  case 1: return DriveMultiplexer::DRIVE_B;
115  default: return DriveMultiplexer::NO_DRIVE;
116  }
117  }();
118  multiplexer.selectDrive(drive, time);
119  multiplexer.setSide ((value & 0x04) != 0);
120  multiplexer.setMotor((value & 0x08) != 0, time);
121  break;
122  }
123  }
124 }
125 
126 byte* CanonFDC::getWriteCacheLine(word address) const
127 {
128  if ((address & 0x3FFF & CacheLine::HIGH) == (0x3FF0 & CacheLine::HIGH)) {
129  return nullptr;
130  } else {
131  return unmappedWrite;
132  }
133 }
134 
135 template<typename Archive>
136 void CanonFDC::serialize(Archive& ar, unsigned /*version*/)
137 {
138  ar.template serializeBase<WD2793BasedFDC>(*this);
139  ar.serialize("controlReg", controlReg);
140 }
143 
144 } // namespace openmsx
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
Definition: CanonFDC.cc:35
void reset(EmuTime::param time) override
This method is called on reset.
Definition: CanonFDC.cc:29
const byte * getReadCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition: CanonFDC.cc:84
void serialize(Archive &ar, unsigned version)
Definition: CanonFDC.cc:136
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
Definition: CanonFDC.cc:61
byte * getWriteCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
Definition: CanonFDC.cc:126
CanonFDC(const DeviceConfig &config)
Definition: CanonFDC.cc:24
void writeMem(word address, byte value, EmuTime::param time) override
Write a given byte to a given location at a certain time to this device.
Definition: CanonFDC.cc:94
void setMotor(bool status, EmuTime::param time) override
Set motor on/off.
bool peekDiskChanged() const override
void selectDrive(DriveNum num, EmuTime::param time)
bool diskChanged() override
Is disk changed?
void setSide(bool side) override
Side select.
static byte unmappedWrite[0x10000]
Definition: MSXDevice.hh:302
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
Definition: MSXFDC.cc:54
const byte * getReadCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition: MSXFDC.cc:59
void reset(EmuTime::param time) override
This method is called on reset.
DriveMultiplexer multiplexer
bool peekIRQ(EmuTime::param time) const
Definition: WD2793.cc:108
byte peekStatusReg(EmuTime::param time) const
Definition: WD2793.cc:208
byte getTrackReg(EmuTime::param time) const
Definition: WD2793.cc:219
byte getDataReg(EmuTime::param time)
Definition: WD2793.cc:258
byte getSectorReg(EmuTime::param time) const
Definition: WD2793.cc:234
bool peekDTRQ(EmuTime::param time) const
Definition: WD2793.cc:93
bool getDTRQ(EmuTime::param time) const
Definition: WD2793.cc:88
byte getStatusReg(EmuTime::param time)
Definition: WD2793.cc:168
byte peekTrackReg(EmuTime::param time) const
Definition: WD2793.cc:224
void setTrackReg(byte value, EmuTime::param time)
Definition: WD2793.cc:214
void setDataReg(byte value, EmuTime::param time)
Definition: WD2793.cc:244
byte peekDataReg(EmuTime::param time) const
Definition: WD2793.cc:323
void setCommandReg(byte value, EmuTime::param time)
Definition: WD2793.cc:120
bool getIRQ(EmuTime::param time) const
Definition: WD2793.cc:103
void setSectorReg(byte value, EmuTime::param time)
Definition: WD2793.cc:229
byte peekSectorReg(EmuTime::param time) const
Definition: WD2793.cc:239
constexpr unsigned HIGH
Definition: CacheLine.hh:10
This file implemented 3 utility functions:
Definition: Autofire.cc:9
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:1009