openMSX
MB89352.cc
Go to the documentation of this file.
1 /* Ported from:
2 ** Source: /cvsroot/bluemsx/blueMSX/Src/IoDevice/MB89352.c,v
3 ** Revision: 1.9
4 ** Date: 2007/03/28 17:35:35
5 **
6 ** More info: http://www.bluemsx.com
7 **
8 ** Copyright (C) 2003-2007 Daniel Vik, white cat
9 */
10 /*
11  * Notes:
12  * Not suppport padding transfer and interrupt signal. (Not used MEGA-SCSI)
13  * Message system might be imperfect. (Not used in MEGA-SCSI usually)
14  */
15 #include "MB89352.hh"
16 #include "SCSIDevice.hh"
17 #include "DummySCSIDevice.hh"
18 #include "SCSIHD.hh"
19 #include "SCSILS120.hh"
20 #include "DeviceConfig.hh"
21 #include "XMLElement.hh"
22 #include "MSXException.hh"
23 #include "enumerate.hh"
24 #include "serialize.hh"
25 #include "xrange.hh"
26 #include <cassert>
27 #include <cstring>
28 #include <memory>
29 
30 namespace openmsx {
31 
32 constexpr byte REG_BDID = 0; // Bus Device ID (r/w)
33 constexpr byte REG_SCTL = 1; // Spc Control (r/w)
34 constexpr byte REG_SCMD = 2; // Command (r/w)
35 constexpr byte REG_OPEN = 3; // (open)
36 constexpr byte REG_INTS = 4; // Interrupt Sense (r/w)
37 constexpr byte REG_PSNS = 5; // Phase Sense (r)
38 constexpr byte REG_SDGC = 5; // SPC Diag. Control (w)
39 constexpr byte REG_SSTS = 6; // SPC SCSI::STATUS (r)
40 constexpr byte REG_SERR = 7; // SPC Error SCSI::STATUS (r/w?)
41 constexpr byte REG_PCTL = 8; // Phase Control (r/w)
42 constexpr byte REG_MBC = 9; // Modified Byte Counter(r)
43 constexpr byte REG_DREG = 10; // Data Register (r/w)
44 constexpr byte REG_TEMP = 11; // Temporary Register (r/w)
45  // Another value is maintained respec-
46  // tively for writing and for reading
47 constexpr byte REG_TCH = 12; // Transfer Counter High(r/w)
48 constexpr byte REG_TCM = 13; // Transfer Counter Mid (r/w)
49 constexpr byte REG_TCL = 14; // Transfer Counter Low (r/w)
50 
51 constexpr byte REG_TEMPWR = 13; // (TEMP register preservation place for writing)
52 constexpr byte FIX_PCTL = 14; // (REG_PCTL & 7)
53 
54 constexpr byte PSNS_IO = 0x01;
55 constexpr byte PSNS_CD = 0x02;
56 constexpr byte PSNS_MSG = 0x04;
57 constexpr byte PSNS_BSY = 0x08;
58 constexpr byte PSNS_SEL = 0x10;
59 constexpr byte PSNS_ATN = 0x20;
60 constexpr byte PSNS_ACK = 0x40;
61 constexpr byte PSNS_REQ = 0x80;
62 
63 constexpr byte PSNS_SELECTION = PSNS_SEL;
64 constexpr byte PSNS_COMMAND = PSNS_CD;
65 constexpr byte PSNS_DATAIN = PSNS_IO;
66 constexpr byte PSNS_DATAOUT = 0;
67 constexpr byte PSNS_STATUS = PSNS_CD | PSNS_IO;
68 constexpr byte PSNS_MSGIN = PSNS_MSG | PSNS_CD | PSNS_IO;
69 constexpr byte PSNS_MSGOUT = PSNS_MSG | PSNS_CD;
70 
71 constexpr byte INTS_ResetCondition = 0x01;
72 constexpr byte INTS_SPC_HardError = 0x02;
73 constexpr byte INTS_TimeOut = 0x04;
74 constexpr byte INTS_ServiceRequited = 0x08;
75 constexpr byte INTS_CommandComplete = 0x10;
76 constexpr byte INTS_Disconnected = 0x20;
77 constexpr byte INTS_ReSelected = 0x40;
78 constexpr byte INTS_Selected = 0x80;
79 
80 constexpr byte CMD_BusRelease = 0x00;
81 constexpr byte CMD_Select = 0x20;
82 constexpr byte CMD_ResetATN = 0x40;
83 constexpr byte CMD_SetATN = 0x60;
84 constexpr byte CMD_Transfer = 0x80;
85 constexpr byte CMD_TransferPause = 0xA0;
86 constexpr byte CMD_Reset_ACK_REQ = 0xC0;
87 constexpr byte CMD_Set_ACK_REQ = 0xE0;
88 constexpr byte CMD_MASK = 0xE0;
89 
91 {
92  // TODO: devBusy = false;
93 
94  // ALMOST COPY PASTED FROM WD33C93:
95 
96  for (const auto* t : config.getXML()->getChildren("target")) {
97  unsigned id = t->getAttributeValueAsInt("id", 0);
98  if (id >= MAX_DEV) {
99  throw MSXException(
100  "Invalid SCSI id: ", id,
101  " (should be 0..", MAX_DEV - 1, ')');
102  }
103  if (dev[id]) {
104  throw MSXException("Duplicate SCSI id: ", id);
105  }
106  DeviceConfig conf(config, *t);
107  auto type = t->getChildData("type");
108  if (type == "SCSIHD") {
109  dev[id] = std::make_unique<SCSIHD>(conf, buffer,
111  } else if (type == "SCSILS120") {
112  dev[id] = std::make_unique<SCSILS120>(conf, buffer,
114  } else {
115  throw MSXException("Unknown SCSI device: ", type);
116  }
117  }
118  // fill remaining targets with dummy SCSI devices to prevent crashes
119  for (auto& d : dev) {
120  if (!d) d = std::make_unique<DummySCSIDevice>();
121  }
122  reset(false);
123 
124  // avoid UMR on savestate
125  memset(buffer.data(), 0, SCSIDevice::BUFFER_SIZE);
126  msgin = 0;
127  blockCounter = 0;
128  nextPhase = SCSI::UNDEFINED;
129  targetId = 0;
130 }
131 
132 void MB89352::disconnect()
133 {
134  if (phase != SCSI::BUS_FREE) {
135  assert(targetId < MAX_DEV);
136  dev[targetId]->disconnect();
137  regs[REG_INTS] |= INTS_Disconnected;
138  phase = SCSI::BUS_FREE;
139  nextPhase = SCSI::UNDEFINED;
140  }
141 
142  regs[REG_PSNS] = 0;
143  isBusy = false;
144  isTransfer = false;
145  counter = 0;
146  tc = 0;
147  atn = 0;
148 }
149 
150 void MB89352::softReset()
151 {
152  isEnabled = false;
153 
154  for (auto i : xrange(2, 15)) {
155  regs[i] = 0;
156  }
157  regs[15] = 0xFF; // un mapped
158  memset(cdb, 0, sizeof(cdb));
159 
160  cdbIdx = 0;
161  bufIdx = 0;
162  phase = SCSI::BUS_FREE;
163  disconnect();
164 }
165 
166 void MB89352::reset(bool scsireset)
167 {
168  regs[REG_BDID] = 0x80; // Initial value
169  regs[REG_SCTL] = 0x80;
170  rst = false;
171  atn = 0;
172  myId = 7;
173 
174  softReset();
175 
176  if (scsireset) {
177  for (auto& d : dev) {
178  d->reset();
179  }
180  }
181 }
182 
183 void MB89352::setACKREQ(byte& value)
184 {
185  // REQ check
186  if ((regs[REG_PSNS] & (PSNS_REQ | PSNS_BSY)) != (PSNS_REQ | PSNS_BSY)) {
187  // set ACK/REQ: REQ/BSY check error
188  if (regs[REG_PSNS] & PSNS_IO) { // SCSI -> SPC
189  value = 0xFF;
190  }
191  return;
192  }
193 
194  // phase check
195  if (regs[FIX_PCTL] != (regs[REG_PSNS] & 7)) {
196  // set ACK/REQ: phase check error
197  if (regs[REG_PSNS] & PSNS_IO) { // SCSI -> SPC
198  value = 0xFF;
199  }
200  if (isTransfer) {
202  }
203  return;
204  }
205 
206  switch (phase) {
207  case SCSI::DATA_IN: // Transfer phase (data in)
208  value = buffer[bufIdx];
209  ++bufIdx;
211  break;
212 
213  case SCSI::DATA_OUT: // Transfer phase (data out)
214  buffer[bufIdx] = value;
215  ++bufIdx;
217  break;
218 
219  case SCSI::COMMAND: // Command phase
220  if (counter < 0) {
221  // Initialize command routine
222  cdbIdx = 0;
223  counter = (value < 0x20) ? 6 : ((value < 0xA0) ? 10 : 12);
224  }
225  cdb[cdbIdx] = value;
226  ++cdbIdx;
228  break;
229 
230  case SCSI::STATUS: // SCSI::STATUS phase
231  value = dev[targetId]->getStatusCode();
233  break;
234 
235  case SCSI::MSG_IN: // Message In phase
236  value = dev[targetId]->msgIn();
237  regs[REG_PSNS] = PSNS_ACK | PSNS_BSY | PSNS_MSGIN;
238  break;
239 
240  case SCSI::MSG_OUT: // Message Out phase
241  msgin |= dev[targetId]->msgOut(value);
243  break;
244 
245  default:
246  // set ACK/REQ code error
247  break;
248  }
249 }
250 
251 void MB89352::resetACKREQ()
252 {
253  // ACK check
254  if ((regs[REG_PSNS] & (PSNS_ACK | PSNS_BSY)) != (PSNS_ACK | PSNS_BSY)) {
255  // reset ACK/REQ: ACK/BSY check error
256  return;
257  }
258 
259  // phase check
260  if (regs[FIX_PCTL] != (regs[REG_PSNS] & 7)) {
261  // reset ACK/REQ: phase check error
262  if (isTransfer) {
264  }
265  return;
266  }
267 
268  switch (phase) {
269  case SCSI::DATA_IN: // Transfer phase (data in)
270  if (--counter > 0) {
272  } else {
273  if (blockCounter > 0) {
274  counter = dev[targetId]->dataIn(blockCounter);
275  if (counter) {
277  bufIdx = 0;
278  break;
279  }
280  }
282  phase = SCSI::STATUS;
283  }
284  break;
285 
286  case SCSI::DATA_OUT: // Transfer phase (data out)
287  if (--counter > 0) {
289  } else {
290  counter = dev[targetId]->dataOut(blockCounter);
291  if (counter) {
293  bufIdx = 0;
294  break;
295  }
297  phase = SCSI::STATUS;
298  }
299  break;
300 
301  case SCSI::COMMAND: // Command phase
302  if (--counter > 0) {
304  } else {
305  bufIdx = 0; // reset buffer index
306  // TODO: devBusy = true;
307  counter = dev[targetId]->executeCmd(cdb, phase, blockCounter);
308  switch (phase) {
309  case SCSI::DATA_IN:
311  break;
312  case SCSI::DATA_OUT:
314  break;
315  case SCSI::STATUS:
317  break;
318  case SCSI::EXECUTE:
319  regs[REG_PSNS] = PSNS_BSY;
320  return; // note: return iso break
321  default:
322  // phase error
323  break;
324  }
325  // TODO: devBusy = false;
326  }
327  break;
328 
329  case SCSI::STATUS: // SCSI::STATUS phase
330  regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_MSGIN;
331  phase = SCSI::MSG_IN;
332  break;
333 
334  case SCSI::MSG_IN: // Message In phase
335  if (msgin <= 0) {
336  disconnect();
337  break;
338  }
339  msgin = 0;
340  [[fallthrough]];
341  case SCSI::MSG_OUT: // Message Out phase
342  if (msgin == -1) {
343  disconnect();
344  return;
345  }
346 
347  if (atn) {
348  if (msgin & 2) {
349  disconnect();
350  return;
351  }
353  return;
354  }
355 
356  if (msgin & 1) {
357  phase = SCSI::MSG_IN;
358  } else {
359  if (msgin & 4) {
360  phase = SCSI::STATUS;
361  nextPhase = SCSI::UNDEFINED;
362  } else {
363  phase = nextPhase;
364  nextPhase = SCSI::UNDEFINED;
365  }
366  }
367 
368  msgin = 0;
369 
370  switch (phase) {
371  case SCSI::COMMAND:
373  break;
374  case SCSI::DATA_IN:
376  break;
377  case SCSI::DATA_OUT:
379  break;
380  case SCSI::STATUS:
382  break;
383  case SCSI::MSG_IN:
384  regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_MSGIN;
385  break;
386  default:
387  // MsgOut code error
388  break;
389  }
390  return;
391 
392  default:
393  //UNREACHABLE;
394  // reset ACK/REQ code error
395  break;
396  }
397 
398  if (atn) {
399  nextPhase = phase;
400  phase = SCSI::MSG_OUT;
402  }
403 }
404 
406 {
407  if (isTransfer && (tc > 0)) {
408  setACKREQ(regs[REG_DREG]);
409  resetACKREQ();
410 
411  --tc;
412  if (tc == 0) {
413  isTransfer = false;
415  }
416  regs[REG_MBC] = (regs[REG_MBC] - 1) & 0x0F;
417  return regs[REG_DREG];
418  } else {
419  return 0xFF;
420  }
421 }
422 
423 void MB89352::writeDREG(byte value)
424 {
425  if (isTransfer && (tc > 0)) {
426  setACKREQ(value);
427  resetACKREQ();
428 
429  --tc;
430  if (tc == 0) {
431  isTransfer = false;
433  }
434  regs[REG_MBC] = (regs[REG_MBC] - 1) & 0x0F;
435  }
436 }
437 
438 void MB89352::writeRegister(byte reg, byte value)
439 {
440  switch (reg) {
441  case REG_DREG: // write data Register
442  writeDREG(value);
443  break;
444 
445  case REG_SCMD: {
446  if (!isEnabled) {
447  break;
448  }
449 
450  // bus reset
451  if (value & 0x10) {
452  if (((regs[REG_SCMD] & 0x10) == 0) & (regs[REG_SCTL] == 0)) {
453  rst = true;
454  regs[REG_INTS] |= INTS_ResetCondition;
455  for (auto& d : dev) {
456  d->busReset();
457  }
458  disconnect(); // alternative routine
459  }
460  } else {
461  rst = false;
462  }
463 
464  regs[REG_SCMD] = value;
465 
466  // execute spc command
467  switch (value & CMD_MASK) {
468  case CMD_Set_ACK_REQ:
469  switch (phase) {
470  case SCSI::DATA_IN:
471  case SCSI::STATUS:
472  case SCSI::MSG_IN:
473  setACKREQ(regs[REG_TEMP]);
474  break;
475  default:
476  setACKREQ(regs[REG_TEMPWR]);
477  }
478  break;
479 
480  case CMD_Reset_ACK_REQ:
481  resetACKREQ();
482  break;
483 
484  case CMD_Select: {
485  if (rst) {
486  regs[REG_INTS] |= INTS_TimeOut;
487  break;
488  }
489 
490  if (regs[REG_PCTL] & 1) {
491  // reselection error
492  regs[REG_INTS] |= INTS_TimeOut;
493  disconnect();
494  break;
495  }
496  bool err = false;
497  int x = regs[REG_BDID] & regs[REG_TEMPWR];
498  if (phase == SCSI::BUS_FREE && x && x != regs[REG_TEMPWR]) {
499  x = regs[REG_TEMPWR] & ~regs[REG_BDID];
500  assert(x != 0); // because of the check 2 lines above
501 
502  // the targetID is calculated.
503  // It is given priority that the number is large.
504  targetId = 0;
505  while (true) {
506  x >>= 1;
507  if (x == 0) break;
508  ++targetId;
509  assert(targetId < MAX_DEV);
510  }
511 
512  if ( dev[targetId]->isSelected()) {
513  // target selection OK
515  isBusy = true;
516  msgin = 0;
517  counter = -1;
518  err = false;
519  if (atn) {
520  phase = SCSI::MSG_OUT;
521  nextPhase = SCSI::COMMAND;
523  } else {
524  phase = SCSI::COMMAND;
525  nextPhase = SCSI::UNDEFINED;
527  }
528  } else {
529  err = true;
530  }
531  } else {
532  err = true;
533  }
534 
535  if (err) {
536  // target selection error
537  regs[REG_INTS] |= INTS_TimeOut;
538  disconnect();
539  }
540  break;
541  }
542  // hardware transfer
543  case CMD_Transfer:
544  if ((regs[FIX_PCTL] == (regs[REG_PSNS] & 7)) &&
545  (regs[REG_PSNS] & (PSNS_REQ | PSNS_BSY))) {
546  isTransfer = true; // set Xfer in Progress
547  } else {
548  // phase error
550  }
551  break;
552 
553  case CMD_BusRelease:
554  disconnect();
555  break;
556 
557  case CMD_SetATN:
558  atn = PSNS_ATN;
559  break;
560 
561  case CMD_ResetATN:
562  atn = 0;
563  break;
564 
565  case CMD_TransferPause:
566  // nothing is done in the initiator.
567  break;
568  }
569  break; // end of REG_SCMD
570  }
571  case REG_INTS: // Reset Interrupts
572  regs[REG_INTS] &= ~value;
573  if (rst) {
574  regs[REG_INTS] |= INTS_ResetCondition;
575  }
576  break;
577 
578  case REG_TEMP:
579  regs[REG_TEMPWR] = value;
580  break;
581 
582  case REG_TCL:
583  tc = (tc & 0xFFFF00) + (value << 0);
584  break;
585 
586  case REG_TCM:
587  tc = (tc & 0xFF00FF) + (value << 8);
588  break;
589 
590  case REG_TCH:
591  tc = (tc & 0x00FFFF) + (value << 16);
592  break;
593 
594  case REG_PCTL:
595  regs[REG_PCTL] = value;
596  regs[FIX_PCTL] = value & 7;
597  break;
598 
599  case REG_BDID:
600  // set Bus Device ID
601  value &= 7;
602  myId = value;
603  regs[REG_BDID] = 1 << value;
604  break;
605 
606  // Nothing
607  case REG_SDGC:
608  case REG_SSTS:
609  case REG_SERR:
610  case REG_MBC:
611  case 15:
612  break;
613 
614  case REG_SCTL: {
615  bool flag = !(value & 0xE0);
616  if (flag != isEnabled) {
617  isEnabled = flag;
618  if (!flag) {
619  softReset();
620  }
621  }
622  [[fallthrough]];
623  }
624  default:
625  regs[reg] = value;
626  }
627 }
628 
629 byte MB89352::getSSTS() const
630 {
631  byte result = 1; // set fifo empty
632  if (isTransfer) {
633  if (regs[REG_PSNS] & PSNS_IO) { // SCSI -> SPC transfer
634  if (tc >= 8) {
635  result = 2; // set fifo full
636  } else {
637  if (tc != 0) {
638  result = 0; // set fifo 1..7 bytes
639  }
640  }
641  }
642  }
643  if (phase != SCSI::BUS_FREE) {
644  result |= 0x80; // set indiciator
645  }
646  if (isBusy) {
647  result |= 0x20; // set SPC_BSY
648  }
649  if ((phase >= SCSI::COMMAND) || isTransfer) {
650  result |= 0x10; // set Xfer in Progress
651  }
652  if (rst) {
653  result |= 0x08; // set SCSI RST
654  }
655  if (tc == 0) {
656  result |= 0x04; // set tc = 0
657  }
658  return result;
659 }
660 
661 byte MB89352::readRegister(byte reg)
662 {
663  switch (reg) {
664  case REG_DREG:
665  return readDREG();
666 
667  case REG_PSNS:
668  if (phase == SCSI::EXECUTE) {
669  counter = dev[targetId]->executingCmd(phase, blockCounter);
670  if (atn && phase != SCSI::EXECUTE) {
671  nextPhase = phase;
672  phase = SCSI::MSG_OUT;
674  } else {
675  switch (phase) {
676  case SCSI::DATA_IN:
678  break;
679  case SCSI::DATA_OUT:
681  break;
682  case SCSI::STATUS:
684  break;
685  case SCSI::EXECUTE:
686  regs[REG_PSNS] = PSNS_BSY;
687  break;
688  default:
689  // phase error
690  break;
691  }
692  }
693  }
694  return regs[REG_PSNS] | atn;
695 
696  default:
697  return peekRegister(reg);
698  }
699 }
700 
701 byte MB89352::peekDREG() const
702 {
703  if (isTransfer && (tc > 0)) {
704  return regs[REG_DREG];
705  } else {
706  return 0xFF;
707  }
708 }
709 
710 byte MB89352::peekRegister(byte reg) const
711 {
712  switch (reg) {
713  case REG_DREG:
714  return peekDREG();
715  case REG_PSNS:
716  return regs[REG_PSNS] | atn;
717  case REG_SSTS:
718  return getSSTS();
719  case REG_TCH:
720  return (tc >> 16) & 0xFF;
721  case REG_TCM:
722  return (tc >> 8) & 0xFF;
723  case REG_TCL:
724  return (tc >> 0) & 0xFF;
725  default:
726  return regs[reg];
727  }
728 }
729 
730 
731 // TODO duplicated in WD33C93.cc
732 static constexpr std::initializer_list<enum_string<SCSI::Phase>> phaseInfo = {
733  { "UNDEFINED", SCSI::UNDEFINED },
734  { "BUS_FREE", SCSI::BUS_FREE },
735  { "ARBITRATION", SCSI::ARBITRATION },
736  { "SELECTION", SCSI::SELECTION },
737  { "RESELECTION", SCSI::RESELECTION },
738  { "COMMAND", SCSI::COMMAND },
739  { "EXECUTE", SCSI::EXECUTE },
740  { "DATA_IN", SCSI::DATA_IN },
741  { "DATA_OUT", SCSI::DATA_OUT },
742  { "STATUS", SCSI::STATUS },
743  { "MSG_OUT", SCSI::MSG_OUT },
744  { "MSG_IN", SCSI::MSG_IN }
745 };
747 
748 template<typename Archive>
749 void MB89352::serialize(Archive& ar, unsigned /*version*/)
750 {
751  ar.serialize_blob("buffer", buffer.data(), buffer.size());
752  char tag[8] = { 'd', 'e', 'v', 'i', 'c', 'e', 'X', 0 };
753  for (auto [i, d] : enumerate(dev)) {
754  tag[6] = char('0' + i);
755  ar.serializePolymorphic(tag, *d);
756  }
757  ar.serialize("bufIdx", bufIdx,
758  "msgin", msgin,
759  "counter", counter,
760  "blockCounter", blockCounter,
761  "tc", tc,
762  "phase", phase,
763  "nextPhase", nextPhase,
764  "myId", myId,
765  "targetId", targetId);
766  ar.serialize_blob("registers", regs, sizeof(regs));
767  ar.serialize("rst", rst,
768  "atn", atn,
769  "isEnabled", isEnabled,
770  "isBusy", isBusy,
771  "isTransfer", isTransfer,
772  "cdbIdx", cdbIdx);
773  ar.serialize_blob("cdb", cdb, sizeof(cdb));
774 }
776 
777 } // namespace openmsx
uintptr_t id
Definition: Interpreter.cc:26
TclObject t
const XMLElement * getXML() const
Definition: DeviceConfig.hh:48
void writeDREG(byte value)
Definition: MB89352.cc:423
byte peekRegister(byte reg) const
Definition: MB89352.cc:710
void writeRegister(byte reg, byte value)
Definition: MB89352.cc:438
byte readRegister(byte reg)
Definition: MB89352.cc:661
void reset(bool scsireset)
Definition: MB89352.cc:166
void serialize(Archive &ar, unsigned version)
Definition: MB89352.cc:749
byte peekDREG() const
Definition: MB89352.cc:701
MB89352(const DeviceConfig &config)
Definition: MB89352.cc:90
byte readDREG()
Definition: MB89352.cc:405
static constexpr unsigned BUFFER_SIZE
Definition: SCSIDevice.hh:23
static constexpr unsigned MODE_MEGASCSI
Definition: SCSIDevice.hh:19
static constexpr unsigned MODE_SCSI2
Definition: SCSIDevice.hh:16
ChildRange getChildren() const
Definition: XMLElement.hh:197
constexpr auto enumerate(Iterable &&iterable)
Heavily inspired by Nathan Reed's blog post: Python-Like enumerate() In C++17 http://reedbeta....
Definition: enumerate.hh:28
@ RESELECTION
Definition: SCSI.hh:104
@ ARBITRATION
Definition: SCSI.hh:102
This file implemented 3 utility functions:
Definition: Autofire.cc:9
constexpr byte PSNS_ACK
Definition: MB89352.cc:60
constexpr byte REG_TEMPWR
Definition: MB89352.cc:51
constexpr byte INTS_ResetCondition
Definition: MB89352.cc:71
constexpr byte REG_TEMP
Definition: MB89352.cc:44
constexpr byte REG_TCH
Definition: MB89352.cc:47
constexpr byte CMD_Set_ACK_REQ
Definition: MB89352.cc:87
constexpr byte PSNS_MSGOUT
Definition: MB89352.cc:69
constexpr byte REG_TCL
Definition: MB89352.cc:49
constexpr byte PSNS_SELECTION
Definition: MB89352.cc:63
constexpr byte REG_SSTS
Definition: MB89352.cc:39
constexpr byte REG_BDID
Definition: MB89352.cc:32
SERIALIZE_ENUM(CassettePlayer::State, stateInfo)
constexpr byte INTS_CommandComplete
Definition: MB89352.cc:75
constexpr byte CMD_ResetATN
Definition: MB89352.cc:82
constexpr byte REG_PSNS
Definition: MB89352.cc:37
constexpr byte REG_TCM
Definition: MB89352.cc:48
constexpr byte CMD_MASK
Definition: MB89352.cc:88
constexpr byte CMD_TransferPause
Definition: MB89352.cc:85
constexpr byte PSNS_MSGIN
Definition: MB89352.cc:68
constexpr byte PSNS_STATUS
Definition: MB89352.cc:67
constexpr byte CMD_Reset_ACK_REQ
Definition: MB89352.cc:86
constexpr byte PSNS_BSY
Definition: MB89352.cc:57
constexpr byte CMD_SetATN
Definition: MB89352.cc:83
constexpr byte PSNS_DATAIN
Definition: MB89352.cc:65
constexpr byte REG_SCMD
Definition: MB89352.cc:34
constexpr byte REG_OPEN
Definition: MB89352.cc:35
constexpr byte INTS_TimeOut
Definition: MB89352.cc:73
constexpr byte INTS_ServiceRequited
Definition: MB89352.cc:74
constexpr byte PSNS_SEL
Definition: MB89352.cc:58
constexpr byte CMD_Select
Definition: MB89352.cc:81
constexpr byte REG_MBC
Definition: MB89352.cc:42
constexpr byte PSNS_REQ
Definition: MB89352.cc:61
constexpr byte REG_SDGC
Definition: MB89352.cc:38
constexpr byte PSNS_IO
Definition: MB89352.cc:54
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:118
constexpr byte PSNS_CD
Definition: MB89352.cc:55
constexpr byte FIX_PCTL
Definition: MB89352.cc:52
constexpr byte PSNS_ATN
Definition: MB89352.cc:59
constexpr byte REG_SCTL
Definition: MB89352.cc:33
constexpr byte INTS_ReSelected
Definition: MB89352.cc:77
constexpr byte INTS_Disconnected
Definition: MB89352.cc:76
constexpr byte INTS_Selected
Definition: MB89352.cc:78
constexpr byte PSNS_COMMAND
Definition: MB89352.cc:64
constexpr byte PSNS_DATAOUT
Definition: MB89352.cc:66
constexpr byte REG_SERR
Definition: MB89352.cc:40
constexpr byte CMD_BusRelease
Definition: MB89352.cc:80
constexpr byte REG_DREG
Definition: MB89352.cc:43
constexpr byte REG_INTS
Definition: MB89352.cc:36
constexpr byte INTS_SPC_HardError
Definition: MB89352.cc:72
constexpr byte CMD_Transfer
Definition: MB89352.cc:84
constexpr byte PSNS_MSG
Definition: MB89352.cc:56
constexpr byte REG_PCTL
Definition: MB89352.cc:41
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:998
constexpr auto xrange(T e)
Definition: xrange.hh:155