MB89352.cc 18 KB

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