12 static const int BUSY = 0x01;
13 static const int INDEX = 0x02;
14 static const int S_DRQ = 0x02;
15 static const int TRACK00 = 0x04;
16 static const int LOST_DATA = 0x04;
17 static const int CRC_ERROR = 0x08;
18 static const int SEEK_ERROR = 0x10;
19 static const int RECORD_NOT_FOUND = 0x10;
20 static const int HEAD_LOADED = 0x20;
21 static const int RECORD_TYPE = 0x20;
22 static const int WRITE_PROTECTED = 0x40;
23 static const int NOT_READY = 0x80;
26 static const int STEP_SPEED = 0x03;
27 static const int V_FLAG = 0x04;
28 static const int E_FLAG = 0x04;
29 static const int H_FLAG = 0x08;
30 static const int T_FLAG = 0x10;
31 static const int M_FLAG = 0x10;
32 static const int N2R_IRQ = 0x01;
33 static const int R2N_IRQ = 0x02;
34 static const int IDX_IRQ = 0x04;
35 static const int IMM_IRQ = 0x08;
86 return time >= drqTime.
getTime();
94 void WD2793::setDrqRate()
102 return INTRQ || immediateIRQ;
110 void WD2793::setIRQ()
115 void WD2793::resetIRQ()
120 bool WD2793::isReady()
const
134 switch (commandReg & 0xF0) {
167 if (((commandReg & 0x80) == 0) || ((commandReg & 0xF0) == 0xD0)) {
169 statusReg &= ~(INDEX | TRACK00 | HEAD_LOADED | WRITE_PROTECTED);
174 statusReg |= TRACK00;
177 statusReg |= HEAD_LOADED;
180 statusReg |= WRITE_PROTECTED;
192 statusReg &= ~NOT_READY;
194 statusReg |= NOT_READY;
245 assert(statusReg & BUSY);
247 if (((commandReg & 0xE0) == 0xA0) ||
248 ((commandReg & 0xF0) == 0xF0)) {
257 statusReg |= LOST_DATA;
259 trackData.
write(dataCurrent++, 0);
266 if ((commandReg & 0xF0) == 0xF0) {
268 bool prevA1 = lastWasA1;
281 crc.
init<0xA1, 0xA1>();
282 }
else if (value == 0xF6) {
285 }
else if (value == 0xF7) {
290 trackData.
write(dataCurrent++, crcVal >> 8);
293 write = crcVal & 0xFF;
294 }
else if (value == 0xFE) {
300 trackData.
addIdam(dataCurrent);
305 trackData.
write(dataCurrent++, write);
309 assert(!dataAvailable || !
getDTRQ(time));
315 if ((((commandReg & 0xE0) == 0x80) ||
316 ((commandReg & 0xF0) == 0xC0) ||
317 ((commandReg & 0xF0) == 0xE0)) &&
319 assert(statusReg & BUSY);
321 dataReg = trackData.
read(dataCurrent++);
326 statusReg |= LOST_DATA;
327 dataReg = trackData.
read(dataCurrent++);
332 assert(!dataAvailable || !
getDTRQ(time));
333 if (dataAvailable == 0) {
334 if ((commandReg & 0xE0) == 0x80) {
337 word diskCrc = 256 * trackData.
read(dataCurrent++);
338 diskCrc += trackData.
read(dataCurrent++);
340 statusReg &= ~CRC_ERROR;
342 statusReg |= CRC_ERROR;
344 if (!(commandReg & M_FLAG)) {
363 if ((((commandReg & 0xE0) == 0x80) ||
364 ((commandReg & 0xF0) == 0xC0) ||
365 ((commandReg & 0xF0) == 0xE0)) &&
367 return trackData.
read(dataCurrent);
393 if ((commandReg & 0x80) == 0x00) {
399 if ((commandReg & 0xC0) == 0x80) {
405 if ((commandReg & 0xC0) == 0x80) {
411 if ((commandReg & 0xC0) == 0x80) {
417 if ((commandReg & 0xC0) == 0x80) {
423 if ((commandReg & 0xE0) == 0xA0) {
425 checkStartWrite(time);
429 if ((commandReg & 0xE0) == 0xA0) {
435 if (((commandReg & 0xC0) == 0xC0) &&
436 ((commandReg & 0xF0) != 0xD0)) {
442 if (((commandReg & 0xC0) == 0xC0) &&
443 ((commandReg & 0xF0) != 0xD0)) {
449 if (((commandReg & 0xC0) == 0xC0) &&
450 ((commandReg & 0xF0) != 0xD0)) {
456 if ((commandReg & 0xF0) == 0xF0) {
468 statusReg &= ~(SEEK_ERROR | CRC_ERROR);
473 switch (commandReg & 0xF0) {
505 if (trackReg == dataReg) {
508 directionIn = (dataReg > trackReg);
515 const int timePerStep[4] = {
520 if ((commandReg & T_FLAG) || ((commandReg & 0xE0) == 0x00)) {
532 drive.
step(directionIn, time);
540 if ((commandReg & 0xE0) == 0x00) {
548 void WD2793::endType1Cmd()
550 if (commandReg & V_FLAG) {
560 statusReg &= ~(LOST_DATA | RECORD_NOT_FOUND |
561 RECORD_TYPE | WRITE_PROTECTED);
570 if (commandReg & E_FLAG) {
590 statusReg |= WRITE_PROTECTED;
601 assert(time < pulse5);
611 }
catch (MSXException& ) {
623 statusReg |= CRC_ERROR;
625 statusReg &= ~CRC_ERROR;
628 (sectorInfo.
track != trackReg) ||
629 (sectorInfo.
sector != sectorReg)) {
641 dataAvailable = 128 << (sectorInfo.
sizeCode & 3);
642 dataCurrent = sectorInfo.
dataIdx;
644 crc.
init<0xA1, 0xA1, 0xA1, 0xFB>();
646 switch (commandReg & 0xE0) {
648 startReadSector(time);
652 startWriteSector(time);
659 statusReg |= RECORD_NOT_FOUND;
665 unsigned gapLength = trackData.
wrapIndex(
668 drqTime += gapLength + 1 + 1;
708 statusReg |= LOST_DATA;
716 drqTime += 12 + 12 + 4;
721 assert((dataAvailable & 0x7F) == 0x7F);
725 void WD2793::doneWriteSector()
729 while (dataAvailable) {
730 statusReg |= LOST_DATA;
731 trackData.
write(dataCurrent++, 0);
741 trackData.
write(dataCurrent++, 0xFE);
746 if (!(commandReg & M_FLAG)) {
753 }
catch (MSXException&) {
756 statusReg |= RECORD_NOT_FOUND;
765 statusReg &= ~(LOST_DATA | RECORD_NOT_FOUND | RECORD_TYPE);
774 if (commandReg & E_FLAG) {
794 statusReg |= WRITE_PROTECTED;
800 if ((commandReg & 0xF0) == 0xC0) {
804 RawTrack::Sector sector;
809 statusReg |= RECORD_NOT_FOUND;
813 dataCurrent = sector.addrIdx;
815 }
catch (MSXException& e) {
816 PRT_DEBUG(
"WD2793: read addr failed: " << e.getMessage()); (void)&e;
817 statusReg |= RECORD_NOT_FOUND;
831 switch (commandReg & 0xF0) {
833 readAddressCmd(time);
859 }
catch (MSXException& e) {
860 PRT_DEBUG(
"WD2793: read track failed: " << e.getMessage()); (void)&e;
877 }
catch (MSXException& ) {
892 void WD2793::doneWriteTrack()
896 while (dataAvailable) {
897 statusReg |= LOST_DATA;
898 trackData.
write(dataCurrent, 0);
903 }
catch (MSXException&) {
916 PRT_DEBUG(
"WD2793 command: Force interrupt");
918 byte flags = commandReg & 0x0F;
919 if (flags & (N2R_IRQ | R2N_IRQ)) {
921 PRT_DEBUG(
"WD2793 type 4 cmd, unimplemented bits " <<
int(flags));
925 immediateIRQ =
false;
927 if ((flags & IDX_IRQ) && isReady()) {
932 if (flags & IMM_IRQ) {
940 void WD2793::endCmd()
948 static enum_string<WD2793::FSMState> fsmStateInfo[] = {
981 template<
typename Archive>
984 ar.template serializeBase<Schedulable>(*this);
986 ar.serialize(
"fsmState", fsmState);
987 ar.serialize(
"statusReg", statusReg);
988 ar.serialize(
"commandReg", commandReg);
989 ar.serialize(
"sectorReg", sectorReg);
990 ar.serialize(
"trackReg", trackReg);
991 ar.serialize(
"dataReg", dataReg);
993 ar.serialize(
"directionIn", directionIn);
994 ar.serialize(
"INTRQ", INTRQ);
995 ar.serialize(
"immediateIRQ", immediateIRQ);
997 ar.serialize(
"dataCurrent", dataCurrent);
998 ar.serialize(
"dataAvailable", dataAvailable);
1000 if (ar.versionAtLeast(version, 2)) {
1001 if (ar.versionAtLeast(version, 4)) {
1002 ar.serialize(
"drqTime", drqTime);
1004 assert(ar.isLoader());
1006 ar.serialize(
"drqTime", c);
1007 drqTime.
reset(c.getTime());
1011 assert(ar.isLoader());
1023 if ((statusReg & BUSY) &&
1024 (((commandReg & 0xC0) == 0x80) ||
1025 ((commandReg & 0xF0) == 0xF0))) {
1027 "Loading an old savestate that had an "
1028 "in-progress WD2793 data-transfer command. "
1029 "This is not fully backwards-compatible and "
1030 "could cause wrong emulation behavior.");
1034 if (ar.versionAtLeast(version, 3)) {
1035 ar.serialize(
"trackData", trackData);
1036 ar.serialize(
"lastWasA1", lastWasA1);
1038 ar.serialize(
"crc", crcVal);
1041 assert(ar.isLoader());
1048 if ((statusReg & BUSY) &&
1049 (((commandReg & 0xC0) == 0x80) ||
1050 ((commandReg & 0xF0) == 0xF0))) {
1052 "Loading an old savestate that had an "
1053 "in-progress WD2793 data-transfer command. "
1054 "This is not fully backwards-compatible and "
1055 "could cause wrong emulation behavior.");
1059 if (ar.versionAtLeast(version, 5)) {
1060 ar.serialize(
"pulse5", pulse5);
1061 ar.serialize(
"sectorInfo", sectorInfo);