scsi.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270
  1. // Copyright (C) 2014 Michael McMaster <michael@codesrc.com>
  2. //
  3. // This file is part of SCSI2SD.
  4. //
  5. // SCSI2SD is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // SCSI2SD is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
  17. #include "scsi.h"
  18. #include "scsiPhy.h"
  19. #include "config.h"
  20. #include "diagnostic.h"
  21. #include "disk.h"
  22. #include "inquiry.h"
  23. #include "led.h"
  24. #include "mode.h"
  25. #include "time.h"
  26. #include "bsp.h"
  27. #include "cdrom.h"
  28. //#include "debug.h"
  29. #include "tape.h"
  30. #include "mo.h"
  31. #include "vendor.h"
  32. #include <string.h>
  33. // Global SCSI device state.
  34. ScsiDevice scsiDev S2S_DMA_ALIGN;
  35. static void enter_SelectionPhase(void);
  36. static void process_SelectionPhase(void);
  37. static void enter_MessageIn(uint8_t message);
  38. static void enter_Status(uint8_t status);
  39. static void enter_DataIn(int len);
  40. static void process_DataIn(void);
  41. static void process_DataOut(void);
  42. static void process_Command(void);
  43. static void doReserveRelease(void);
  44. void enter_BusFree()
  45. {
  46. // This delay probably isn't needed for most SCSI hosts, but it won't
  47. // hurt either. It's possible some of the samplers needed this delay.
  48. if (scsiDev.compatMode < COMPAT_SCSI2)
  49. {
  50. s2s_delay_us(2);
  51. }
  52. #if 0
  53. if (scsiDev.status != GOOD && isDebugEnabled())
  54. {
  55. // We want to capture debug information for failure cases.
  56. s2s_delay_ms(64);
  57. }
  58. #endif
  59. scsiEnterBusFree();
  60. // Wait for the initiator to cease driving signals
  61. // Bus settle delay + bus clear delay = 1200ns
  62. s2s_delay_us(2);
  63. s2s_ledOff();
  64. scsiDev.phase = BUS_FREE;
  65. scsiDev.selFlag = 0;
  66. }
  67. static void enter_MessageIn(uint8_t message)
  68. {
  69. scsiDev.msgIn = message;
  70. scsiDev.phase = MESSAGE_IN;
  71. }
  72. int process_MessageIn(int releaseBusFree)
  73. {
  74. scsiEnterPhase(MESSAGE_IN);
  75. scsiWriteByte(scsiDev.msgIn);
  76. if (unlikely(scsiDev.atnFlag))
  77. {
  78. // If there was a parity error, we go
  79. // back to MESSAGE_OUT first, get out parity error message, then come
  80. // back here.
  81. return 0;
  82. }
  83. else if ((scsiDev.msgIn == MSG_LINKED_COMMAND_COMPLETE) ||
  84. (scsiDev.msgIn == MSG_LINKED_COMMAND_COMPLETE_WITH_FLAG))
  85. {
  86. // Go back to the command phase and start again.
  87. scsiDev.phase = COMMAND;
  88. scsiDev.dataPtr = 0;
  89. scsiDev.savedDataPtr = 0;
  90. scsiDev.dataLen = 0;
  91. scsiDev.status = GOOD;
  92. transfer.blocks = 0;
  93. transfer.currentBlock = 0;
  94. return 0;
  95. }
  96. else if (releaseBusFree) /*if (scsiDev.msgIn == MSG_COMMAND_COMPLETE)*/
  97. {
  98. enter_BusFree();
  99. return 1;
  100. }
  101. else
  102. {
  103. return 1;
  104. }
  105. }
  106. static void messageReject()
  107. {
  108. scsiEnterPhase(MESSAGE_IN);
  109. scsiWriteByte(MSG_REJECT);
  110. }
  111. static void enter_Status(uint8_t status)
  112. {
  113. scsiDev.status = status;
  114. scsiDev.phase = STATUS;
  115. scsiDev.lastStatus = scsiDev.status;
  116. scsiDev.lastSense = scsiDev.target->sense.code;
  117. scsiDev.lastSenseASC = scsiDev.target->sense.asc;
  118. }
  119. void process_Status()
  120. {
  121. scsiEnterPhase(STATUS);
  122. uint8_t message;
  123. uint8_t control = scsiDev.cdb[scsiDev.cdbLen - 1];
  124. if (scsiDev.target->cfg->quirks == S2S_CFG_QUIRKS_OMTI)
  125. {
  126. // OMTI non-standard LINK control
  127. if (control & 0x01)
  128. {
  129. scsiDev.phase = COMMAND;
  130. return;
  131. }
  132. }
  133. if ((scsiDev.status == GOOD) && (control & 0x01) &&
  134. scsiDev.target->cfg->quirks != S2S_CFG_QUIRKS_XEBEC)
  135. {
  136. // Linked command.
  137. scsiDev.status = INTERMEDIATE;
  138. if (control & 0x02)
  139. {
  140. message = MSG_LINKED_COMMAND_COMPLETE_WITH_FLAG;
  141. }
  142. else
  143. {
  144. message = MSG_LINKED_COMMAND_COMPLETE;
  145. }
  146. }
  147. else
  148. {
  149. message = MSG_COMMAND_COMPLETE;
  150. }
  151. if (scsiDev.target->cfg->quirks == S2S_CFG_QUIRKS_XEBEC)
  152. {
  153. // More non-standardness. Expects 2 status bytes (really status + msg)
  154. // 00 d 000 err 0
  155. // d == disk number
  156. // ERR = 1 if error.
  157. if (scsiDev.status == GOOD)
  158. {
  159. scsiWriteByte(scsiDev.cdb[1] & 0x20);
  160. }
  161. else
  162. {
  163. scsiWriteByte((scsiDev.cdb[1] & 0x20) | 0x2);
  164. }
  165. s2s_delay_us(10); // Seems to need a delay before changing phase bits.
  166. }
  167. else if (scsiDev.target->cfg->quirks == S2S_CFG_QUIRKS_OMTI)
  168. {
  169. scsiDev.status |= (scsiDev.target->targetId & 0x03) << 5;
  170. scsiWriteByte(scsiDev.status);
  171. }
  172. else
  173. {
  174. scsiWriteByte(scsiDev.status);
  175. }
  176. scsiDev.lastStatus = scsiDev.status;
  177. scsiDev.lastSense = scsiDev.target->sense.code;
  178. scsiDev.lastSenseASC = scsiDev.target->sense.asc;
  179. // Command Complete occurs AFTER a valid status has been
  180. // sent. then we go bus-free.
  181. enter_MessageIn(message);
  182. }
  183. static void enter_DataIn(int len)
  184. {
  185. scsiDev.dataLen = len;
  186. scsiDev.phase = DATA_IN;
  187. }
  188. static void process_DataIn()
  189. {
  190. uint32_t len;
  191. if (scsiDev.dataLen > sizeof(scsiDev.data))
  192. {
  193. scsiDev.dataLen = sizeof(scsiDev.data);
  194. }
  195. len = scsiDev.dataLen - scsiDev.dataPtr;
  196. if (len > 0)
  197. {
  198. scsiEnterPhase(DATA_IN);
  199. scsiWrite(scsiDev.data + scsiDev.dataPtr, len);
  200. scsiDev.dataPtr += len;
  201. }
  202. if ((scsiDev.dataPtr >= scsiDev.dataLen) &&
  203. (transfer.currentBlock == transfer.blocks))
  204. {
  205. enter_Status(GOOD);
  206. }
  207. }
  208. static void process_DataOut()
  209. {
  210. uint32_t len;
  211. if (scsiDev.dataLen > sizeof(scsiDev.data))
  212. {
  213. scsiDev.dataLen = sizeof(scsiDev.data);
  214. }
  215. len = scsiDev.dataLen - scsiDev.dataPtr;
  216. if (len > 0)
  217. {
  218. scsiEnterPhase(DATA_OUT);
  219. int parityError = 0;
  220. scsiRead(scsiDev.data + scsiDev.dataPtr, len, &parityError);
  221. scsiDev.dataPtr += len;
  222. if (parityError &&
  223. (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY))
  224. {
  225. scsiDev.target->sense.code = ABORTED_COMMAND;
  226. scsiDev.target->sense.asc = SCSI_PARITY_ERROR;
  227. enter_Status(CHECK_CONDITION);
  228. }
  229. }
  230. if ((scsiDev.dataPtr >= scsiDev.dataLen) &&
  231. (transfer.currentBlock == transfer.blocks))
  232. {
  233. if (scsiDev.postDataOutHook != NULL)
  234. {
  235. scsiDev.postDataOutHook();
  236. }
  237. else
  238. {
  239. enter_Status(GOOD);
  240. }
  241. }
  242. }
  243. static const uint8_t CmdGroupBytes[8] = {6, 10, 10, 6, 6, 12, 6, 6};
  244. static void process_Command()
  245. {
  246. int group;
  247. uint8_t command;
  248. uint8_t control;
  249. scsiEnterPhase(COMMAND);
  250. memset(scsiDev.cdb + 6, 0, sizeof(scsiDev.cdb) - 6);
  251. int parityError = 0;
  252. scsiRead(scsiDev.cdb, 6, &parityError);
  253. group = scsiDev.cdb[0] >> 5;
  254. scsiDev.cdbLen = CmdGroupBytes[group];
  255. if (parityError &&
  256. (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY))
  257. {
  258. // Don't try and read more bytes, as we cannot be sure what group
  259. // the command should be.
  260. }
  261. else if (scsiDev.cdbLen - 6 > 0)
  262. {
  263. scsiRead(scsiDev.cdb + 6, scsiDev.cdbLen - 6, &parityError);
  264. }
  265. command = scsiDev.cdb[0];
  266. // Prefer LUN's set by IDENTIFY messages for newer hosts.
  267. if (scsiDev.lun < 0)
  268. {
  269. if (command == 0xE0 || command == 0xE4) // XEBEC s1410
  270. {
  271. scsiDev.lun = 0;
  272. }
  273. else
  274. {
  275. scsiDev.lun = scsiDev.cdb[1] >> 5;
  276. }
  277. }
  278. // For Philips P2000C with Xebec S1410 SASI/MFM adapter
  279. // http://bitsavers.trailing-edge.com/pdf/xebec/104524C_S1410Man_Aug83.pdf
  280. if ((scsiDev.lun > 0) && (scsiDev.boardCfg.flags & S2S_CFG_MAP_LUNS_TO_IDS))
  281. {
  282. int tgtIndex;
  283. for (tgtIndex = 0; tgtIndex < S2S_MAX_TARGETS; ++tgtIndex)
  284. {
  285. if (scsiDev.targets[tgtIndex].targetId == scsiDev.lun)
  286. {
  287. scsiDev.target = &scsiDev.targets[tgtIndex];
  288. scsiDev.lun = 0;
  289. break;
  290. }
  291. }
  292. }
  293. control = scsiDev.cdb[scsiDev.cdbLen - 1];
  294. scsiDev.cmdCount++;
  295. const S2S_TargetCfg* cfg = scsiDev.target->cfg;
  296. if (unlikely(scsiDev.resetFlag))
  297. {
  298. // Don't log bogus commands
  299. scsiDev.cmdCount--;
  300. memset(scsiDev.cdb, 0xff, sizeof(scsiDev.cdb));
  301. return;
  302. }
  303. else if (parityError &&
  304. (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY))
  305. {
  306. scsiDev.target->sense.code = ABORTED_COMMAND;
  307. scsiDev.target->sense.asc = SCSI_PARITY_ERROR;
  308. enter_Status(CHECK_CONDITION);
  309. }
  310. else if ((control & 0x02) && ((control & 0x01) == 0) &&
  311. // used for head step options on xebec.
  312. likely(scsiDev.target->cfg->quirks != S2S_CFG_QUIRKS_XEBEC))
  313. {
  314. // FLAG set without LINK flag.
  315. scsiDev.target->sense.code = ILLEGAL_REQUEST;
  316. scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
  317. enter_Status(CHECK_CONDITION);
  318. }
  319. else if (command == 0x12)
  320. {
  321. s2s_scsiInquiry();
  322. }
  323. else if (command == 0x03)
  324. {
  325. // REQUEST SENSE
  326. uint32_t allocLength = scsiDev.cdb[4];
  327. if (scsiDev.target->cfg->quirks == S2S_CFG_QUIRKS_XEBEC)
  328. {
  329. // Completely non-standard
  330. allocLength = 4;
  331. if (scsiDev.target->sense.code == NO_SENSE)
  332. scsiDev.data[0] = 0;
  333. else if (scsiDev.target->sense.code == ILLEGAL_REQUEST)
  334. scsiDev.data[0] = 0x20; // Illegal command
  335. else if (scsiDev.target->sense.code == NOT_READY)
  336. scsiDev.data[0] = 0x04; // Drive not ready
  337. else
  338. scsiDev.data[0] = 0x11; // Uncorrectable data error
  339. scsiDev.data[1] = (scsiDev.cdb[1] & 0x20) | ((transfer.lba >> 16) & 0x1F);
  340. scsiDev.data[2] = transfer.lba >> 8;
  341. scsiDev.data[3] = transfer.lba;
  342. }
  343. else
  344. {
  345. // As specified by the SASI and SCSI1 standard.
  346. // Newer initiators won't be specifying 0 anyway.
  347. if (allocLength == 0) allocLength = 4;
  348. memset(scsiDev.data, 0, 256); // Max possible alloc length
  349. scsiDev.data[0] = 0xF0;
  350. scsiDev.data[2] = scsiDev.target->sense.code & 0x0F;
  351. scsiDev.data[3] = transfer.lba >> 24;
  352. scsiDev.data[4] = transfer.lba >> 16;
  353. scsiDev.data[5] = transfer.lba >> 8;
  354. scsiDev.data[6] = transfer.lba;
  355. // Additional bytes if there are errors to report
  356. scsiDev.data[7] = 10; // additional length
  357. scsiDev.data[12] = scsiDev.target->sense.asc >> 8;
  358. scsiDev.data[13] = scsiDev.target->sense.asc;
  359. }
  360. // Silently truncate results. SCSI-2 spec 8.2.14.
  361. enter_DataIn(allocLength);
  362. // This is a good time to clear out old sense information.
  363. scsiDev.target->sense.code = NO_SENSE;
  364. scsiDev.target->sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;
  365. }
  366. // Some old SCSI drivers do NOT properly support
  367. // unitAttention. eg. the Mac Plus would trigger a SCSI reset
  368. // on receiving the unit attention response on boot, thus
  369. // triggering another unit attention condition.
  370. else if (scsiDev.target->unitAttention &&
  371. (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_UNIT_ATTENTION))
  372. {
  373. scsiDev.target->sense.code = UNIT_ATTENTION;
  374. scsiDev.target->sense.asc = scsiDev.target->unitAttention;
  375. // If initiator doesn't do REQUEST SENSE for the next command, then
  376. // data is lost.
  377. scsiDev.target->unitAttention = 0;
  378. enter_Status(CHECK_CONDITION);
  379. }
  380. else if (scsiDev.lun)
  381. {
  382. scsiDev.target->sense.code = ILLEGAL_REQUEST;
  383. scsiDev.target->sense.asc = LOGICAL_UNIT_NOT_SUPPORTED;
  384. enter_Status(CHECK_CONDITION);
  385. }
  386. else if (command == 0x17 || command == 0x16)
  387. {
  388. doReserveRelease();
  389. }
  390. else if ((scsiDev.target->reservedId >= 0) &&
  391. (scsiDev.target->reservedId != scsiDev.initiatorId))
  392. {
  393. enter_Status(CONFLICT);
  394. }
  395. // Handle odd device types first that may override basic read and
  396. // write commands. Will fall-through to generic disk handling.
  397. else if (((cfg->deviceType == S2S_CFG_OPTICAL) && scsiCDRomCommand()) ||
  398. ((cfg->deviceType == S2S_CFG_SEQUENTIAL) && scsiTapeCommand()) ||
  399. ((cfg->deviceType == S2S_CFG_MO) && scsiMOCommand()))
  400. {
  401. // Already handled.
  402. }
  403. else if (scsiDiskCommand())
  404. {
  405. // Already handled.
  406. // check for the performance-critical read/write
  407. // commands ASAP.
  408. }
  409. else if (command == 0x1C)
  410. {
  411. scsiReceiveDiagnostic();
  412. }
  413. else if (command == 0x1D)
  414. {
  415. scsiSendDiagnostic();
  416. }
  417. else if (command == 0x3B)
  418. {
  419. scsiWriteBuffer();
  420. }
  421. else if (command == 0x0f &&
  422. scsiDev.target->cfg->quirks == S2S_CFG_QUIRKS_XEBEC)
  423. {
  424. scsiWriteSectorBuffer();
  425. }
  426. else if (command == 0x3C)
  427. {
  428. scsiReadBuffer();
  429. }
  430. else if (!scsiModeCommand() && !scsiVendorCommand())
  431. {
  432. scsiDev.target->sense.code = ILLEGAL_REQUEST;
  433. scsiDev.target->sense.asc = INVALID_COMMAND_OPERATION_CODE;
  434. enter_Status(CHECK_CONDITION);
  435. }
  436. // Successful
  437. if (scsiDev.phase == COMMAND) // No status set, and not in DATA_IN
  438. {
  439. enter_Status(GOOD);
  440. }
  441. }
  442. static void doReserveRelease()
  443. {
  444. int extentReservation = scsiDev.cdb[1] & 1;
  445. int thirdPty = scsiDev.cdb[1] & 0x10;
  446. int thirdPtyId = (scsiDev.cdb[1] >> 1) & 0x7;
  447. uint8_t command = scsiDev.cdb[0];
  448. int canRelease =
  449. (!thirdPty && (scsiDev.initiatorId == scsiDev.target->reservedId)) ||
  450. (thirdPty &&
  451. (scsiDev.target->reserverId == scsiDev.initiatorId) &&
  452. (scsiDev.target->reservedId == thirdPtyId)
  453. );
  454. if (extentReservation)
  455. {
  456. // Not supported.
  457. scsiDev.target->sense.code = ILLEGAL_REQUEST;
  458. scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
  459. enter_Status(CHECK_CONDITION);
  460. }
  461. else if (command == 0x17) // release
  462. {
  463. if ((scsiDev.target->reservedId < 0) || canRelease)
  464. {
  465. scsiDev.target->reservedId = -1;
  466. scsiDev.target->reserverId = -1;
  467. }
  468. else
  469. {
  470. enter_Status(CONFLICT);
  471. }
  472. }
  473. else // assume reserve.
  474. {
  475. if ((scsiDev.target->reservedId < 0) || canRelease)
  476. {
  477. scsiDev.target->reserverId = scsiDev.initiatorId;
  478. if (thirdPty)
  479. {
  480. scsiDev.target->reservedId = thirdPtyId;
  481. }
  482. else
  483. {
  484. scsiDev.target->reservedId = scsiDev.initiatorId;
  485. }
  486. }
  487. else
  488. {
  489. // Already reserved by someone else!
  490. enter_Status(CONFLICT);
  491. }
  492. }
  493. }
  494. static uint32_t resetUntil = 0;
  495. static void scsiReset()
  496. {
  497. scsiDev.rstCount++;
  498. s2s_ledOff();
  499. scsiPhyReset();
  500. scsiDev.phase = BUS_FREE;
  501. scsiDev.atnFlag = 0;
  502. scsiDev.resetFlag = 0;
  503. scsiDev.selFlag = 0;
  504. scsiDev.lun = -1;
  505. scsiDev.compatMode = COMPAT_UNKNOWN;
  506. if (scsiDev.target)
  507. {
  508. if (scsiDev.target->unitAttention != POWER_ON_RESET)
  509. {
  510. scsiDev.target->unitAttention = SCSI_BUS_RESET;
  511. }
  512. scsiDev.target->reservedId = -1;
  513. scsiDev.target->reserverId = -1;
  514. scsiDev.target->sense.code = NO_SENSE;
  515. scsiDev.target->sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;
  516. }
  517. scsiDev.target = NULL;
  518. for (int i = 0; i < S2S_MAX_TARGETS; ++i)
  519. {
  520. scsiDev.targets[i].syncOffset = 0;
  521. scsiDev.targets[i].syncPeriod = 0;
  522. }
  523. scsiDev.minSyncPeriod = 0;
  524. scsiDiskReset();
  525. scsiDev.postDataOutHook = NULL;
  526. scsiDev.sdUnderrunCount = 0;
  527. // Sleep to allow the bus to settle down a bit.
  528. // We must be ready again within the "Reset to selection time" of
  529. // 250ms.
  530. // There is no guarantee that the RST line will be negated by then.
  531. // NOTE: We could be connected and powered by USB for configuration,
  532. // in which case TERMPWR cannot be supplied, and reset will ALWAYS
  533. // be true. Therefore, the sleep here must be slow to avoid slowing
  534. // USB comms
  535. resetUntil = s2s_getTime_ms() + 2; // At least 1ms.
  536. }
  537. static void enter_SelectionPhase()
  538. {
  539. // Ignore stale versions of this flag, but ensure we know the
  540. // current value if the flag is still set.
  541. scsiDev.atnFlag = 0;
  542. scsiDev.dataPtr = 0;
  543. scsiDev.savedDataPtr = 0;
  544. scsiDev.dataLen = 0;
  545. scsiDev.status = GOOD;
  546. scsiDev.phase = SELECTION;
  547. scsiDev.lun = -1;
  548. scsiDev.discPriv = 0;
  549. scsiDev.initiatorId = -1;
  550. scsiDev.target = NULL;
  551. transfer.blocks = 0;
  552. transfer.currentBlock = 0;
  553. scsiDev.postDataOutHook = NULL;
  554. scsiDev.needSyncNegotiationAck = 0;
  555. }
  556. static void process_SelectionPhase()
  557. {
  558. // Selection delays.
  559. // Many SCSI1 samplers that use a 5380 chip need a delay of at least 1ms.
  560. // The Mac Plus boot-time (ie. rom code) selection abort time
  561. // is < 1ms and must have no delay (standard suggests 250ms abort time)
  562. // Most newer SCSI2 hosts don't care either way.
  563. if (scsiDev.target->cfg->quirks == S2S_CFG_QUIRKS_XEBEC)
  564. {
  565. s2s_delay_ms(1); // Simply won't work if set to 0.
  566. }
  567. else if (scsiDev.boardCfg.selectionDelay == 255) // auto
  568. {
  569. if (scsiDev.compatMode < COMPAT_SCSI2)
  570. {
  571. s2s_delay_ms(1);
  572. }
  573. }
  574. else if (scsiDev.boardCfg.selectionDelay != 0)
  575. {
  576. s2s_delay_ms(scsiDev.boardCfg.selectionDelay);
  577. }
  578. uint8_t selStatus = *SCSI_STS_SELECTED;
  579. if ((selStatus == 0) && (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_SEL_LATCH))
  580. {
  581. selStatus = scsiDev.selFlag;
  582. }
  583. int tgtIndex;
  584. TargetState* target = NULL;
  585. for (tgtIndex = 0; tgtIndex < S2S_MAX_TARGETS; ++tgtIndex)
  586. {
  587. if (scsiDev.targets[tgtIndex].targetId == (selStatus & 7))
  588. {
  589. target = &scsiDev.targets[tgtIndex];
  590. break;
  591. }
  592. }
  593. if ((target != NULL) && (selStatus & 0x40))
  594. {
  595. // We've been selected!
  596. // Assert BSY - Selection success!
  597. // must happen within 200us (Selection abort time) of seeing our
  598. // ID + SEL.
  599. // (Note: the initiator will be waiting the "Selection time-out delay"
  600. // for our BSY response, which is actually a very generous 250ms)
  601. *SCSI_CTRL_BSY = 1;
  602. s2s_ledOn();
  603. scsiDev.target = target;
  604. // Do we enter MESSAGE OUT immediately ? SCSI 1 and 2 standards says
  605. // move to MESSAGE OUT if ATN is true before we assert BSY.
  606. // The initiator should assert ATN with SEL.
  607. scsiDev.atnFlag = selStatus & 0x80;
  608. // Unit attention breaks many older SCSI hosts. Disable it completely
  609. // for SCSI-1 (and older) hosts, regardless of our configured setting.
  610. // Enable the compatability mode also as many SASI and SCSI1
  611. // controllers don't generate parity bits.
  612. if (!scsiDev.atnFlag)
  613. {
  614. target->unitAttention = 0;
  615. scsiDev.compatMode = COMPAT_SCSI1;
  616. }
  617. else if (!(scsiDev.boardCfg.flags & S2S_CFG_ENABLE_SCSI2))
  618. {
  619. scsiDev.compatMode = COMPAT_SCSI2_DISABLED;
  620. }
  621. else
  622. {
  623. scsiDev.compatMode = COMPAT_SCSI2;
  624. }
  625. scsiDev.selCount++;
  626. // Save our initiator now that we're no longer in a time-critical
  627. // section.
  628. // SCSI1/SASI initiators may not set their own ID.
  629. scsiDev.initiatorId = (selStatus >> 3) & 0x7;
  630. // Wait until the end of the selection phase.
  631. uint32_t selTimerBegin = s2s_getTime_ms();
  632. while (likely(!scsiDev.resetFlag))
  633. {
  634. if (!scsiStatusSEL())
  635. {
  636. break;
  637. }
  638. else if (s2s_elapsedTime_ms(selTimerBegin) >= 10 &&
  639. scsiDev.target->cfg->quirks == S2S_CFG_QUIRKS_XEBEC)
  640. {
  641. // XEBEC hosts may not bother releasing SEL at all until
  642. // just before the command ends.
  643. break;
  644. }
  645. else if (s2s_elapsedTime_ms(selTimerBegin) >= 250)
  646. {
  647. *SCSI_CTRL_BSY = 0;
  648. scsiDev.resetFlag = 1;
  649. break;
  650. }
  651. }
  652. scsiDev.phase = COMMAND;
  653. }
  654. else if (!selStatus)
  655. {
  656. scsiDev.phase = BUS_BUSY;
  657. }
  658. scsiDev.selFlag = 0;
  659. }
  660. static void process_MessageOut()
  661. {
  662. int wasNeedSyncNegotiationAck = scsiDev.needSyncNegotiationAck;
  663. scsiDev.needSyncNegotiationAck = 0; // Successful on -most- messages.
  664. scsiEnterPhase(MESSAGE_OUT);
  665. scsiDev.atnFlag = 0;
  666. scsiDev.msgOut = scsiReadByte();
  667. scsiDev.msgCount++;
  668. if (scsiParityError() &&
  669. (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY))
  670. {
  671. // Skip the remaining message bytes, and then start the MESSAGE_OUT
  672. // phase again from the start. The initiator will re-send the
  673. // same set of messages.
  674. while (scsiStatusATN() && !scsiDev.resetFlag)
  675. {
  676. scsiReadByte();
  677. }
  678. // Go-back and try the message again.
  679. scsiDev.atnFlag = 1;
  680. }
  681. else if (scsiDev.msgOut == 0x00)
  682. {
  683. // COMMAND COMPLETE. but why would the target be receiving this ? nfi.
  684. enter_BusFree();
  685. }
  686. else if (scsiDev.msgOut == 0x06)
  687. {
  688. // ABORT
  689. scsiDiskReset();
  690. enter_BusFree();
  691. }
  692. else if (scsiDev.msgOut == 0x0C)
  693. {
  694. // BUS DEVICE RESET
  695. scsiDiskReset();
  696. scsiDev.target->unitAttention = SCSI_BUS_RESET;
  697. // ANY initiator can reset the reservation state via this message.
  698. scsiDev.target->reservedId = -1;
  699. scsiDev.target->reserverId = -1;
  700. // Cancel any sync negotiation
  701. scsiDev.target->syncOffset = 0;
  702. scsiDev.target->syncPeriod = 0;
  703. enter_BusFree();
  704. }
  705. else if (scsiDev.msgOut == 0x05)
  706. {
  707. // Initiate Detected Error
  708. // Ignore for now
  709. }
  710. else if (scsiDev.msgOut == 0x0F)
  711. {
  712. // INITIATE RECOVERY
  713. // Ignore for now
  714. }
  715. else if (scsiDev.msgOut == 0x10)
  716. {
  717. // RELEASE RECOVERY
  718. // Ignore for now
  719. enter_BusFree();
  720. }
  721. else if (scsiDev.msgOut == MSG_REJECT)
  722. {
  723. // Message Reject
  724. // Oh well.
  725. if (wasNeedSyncNegotiationAck)
  726. {
  727. scsiDev.target->syncOffset = 0;
  728. scsiDev.target->syncPeriod = 0;
  729. }
  730. }
  731. else if (scsiDev.msgOut == 0x08)
  732. {
  733. // NOP
  734. }
  735. else if (scsiDev.msgOut == 0x09)
  736. {
  737. // Message Parity Error
  738. // Go back and re-send the last message.
  739. scsiDev.phase = MESSAGE_IN;
  740. if (wasNeedSyncNegotiationAck)
  741. {
  742. scsiDev.target->syncOffset = 0;
  743. scsiDev.target->syncPeriod = 0;
  744. }
  745. }
  746. else if (scsiDev.msgOut & 0x80) // 0x80 -> 0xFF
  747. {
  748. // IDENTIFY
  749. if ((scsiDev.msgOut & 0x18) || // Reserved bits set.
  750. (scsiDev.msgOut & 0x20)) // We don't have any target routines!
  751. {
  752. messageReject();
  753. }
  754. scsiDev.lun = scsiDev.msgOut & 0x7;
  755. scsiDev.discPriv =
  756. ((scsiDev.msgOut & 0x40) && (scsiDev.initiatorId >= 0))
  757. ? 1 : 0;
  758. }
  759. else if (scsiDev.msgOut >= 0x20 && scsiDev.msgOut <= 0x2F)
  760. {
  761. // Two byte message. We don't support these. read and discard.
  762. scsiReadByte();
  763. if (scsiDev.msgOut == 0x23) {
  764. // Ignore Wide Residue. We're only 8 bit anyway.
  765. } else {
  766. messageReject();
  767. }
  768. }
  769. else if (scsiDev.msgOut == 0x01)
  770. {
  771. int i;
  772. // Extended message.
  773. int msgLen = scsiReadByte();
  774. if (msgLen == 0) msgLen = 256;
  775. uint8_t extmsg[256];
  776. for (i = 0; i < msgLen && !scsiDev.resetFlag; ++i)
  777. {
  778. // Discard bytes.
  779. extmsg[i] = scsiReadByte();
  780. }
  781. if (extmsg[0] == 3 && msgLen == 2) // Wide Data Request
  782. {
  783. // Negotiate down to 8bit
  784. scsiEnterPhase(MESSAGE_IN);
  785. static const uint8_t WDTR[] = {0x01, 0x02, 0x03, 0x00};
  786. scsiWrite(WDTR, sizeof(WDTR));
  787. // SDTR becomes invalidated.
  788. scsiDev.target->syncOffset = 0;
  789. scsiDev.target->syncPeriod = 0;
  790. }
  791. else if (extmsg[0] == 1 && msgLen == 3) // Synchronous data request
  792. {
  793. int oldPeriod = scsiDev.target->syncPeriod;
  794. int oldOffset = scsiDev.target->syncOffset;
  795. int transferPeriod = extmsg[1];
  796. int offset = extmsg[2];
  797. if ((
  798. (transferPeriod > 0) &&
  799. (transferPeriod < scsiDev.minSyncPeriod)) ||
  800. (scsiDev.minSyncPeriod == 0))
  801. {
  802. scsiDev.minSyncPeriod = transferPeriod;
  803. }
  804. if ((transferPeriod > 80) || // 320ns, 3.125MB/s
  805. // Amiga A590 (WD33C93 chip) only does 3.5MB/s sync
  806. // After 80 we start to run out of bits in the fpga timing
  807. // register.
  808. (transferPeriod == 0) ||
  809. (offset == 0) ||
  810. ((scsiDev.boardCfg.scsiSpeed != S2S_CFG_SPEED_NoLimit) &&
  811. (scsiDev.boardCfg.scsiSpeed <= S2S_CFG_SPEED_ASYNC_50)))
  812. {
  813. scsiDev.target->syncOffset = 0;
  814. scsiDev.target->syncPeriod = 0;
  815. } else {
  816. scsiDev.target->syncOffset = offset <= 15 ? offset : 15;
  817. // FAST20 / 50ns / 20MHz is disabled for now due to
  818. // data corruption while reading data. We can count the
  819. // ACK's correctly, but can't save the data to a register
  820. // before it changes. (ie. transferPeriod == 12)
  821. if ((scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_TURBO) &&
  822. (transferPeriod <= 16))
  823. {
  824. scsiDev.target->syncPeriod = 16; // 15.6MB/s
  825. }
  826. else if (scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_TURBO)
  827. {
  828. scsiDev.target->syncPeriod = transferPeriod;
  829. }
  830. else if (transferPeriod <= 25 &&
  831. ((scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_NoLimit) ||
  832. (scsiDev.boardCfg.scsiSpeed >= S2S_CFG_SPEED_SYNC_10)))
  833. {
  834. scsiDev.target->syncPeriod = 25; // 100ns, 10MB/s
  835. } else if (transferPeriod < 50 &&
  836. ((scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_NoLimit) ||
  837. (scsiDev.boardCfg.scsiSpeed >= S2S_CFG_SPEED_SYNC_10)))
  838. {
  839. scsiDev.target->syncPeriod = transferPeriod;
  840. } else if (transferPeriod >= 50)
  841. {
  842. scsiDev.target->syncPeriod = transferPeriod;
  843. } else {
  844. scsiDev.target->syncPeriod = 50;
  845. }
  846. }
  847. if (transferPeriod != oldPeriod ||
  848. scsiDev.target->syncPeriod != oldPeriod ||
  849. offset != oldOffset ||
  850. scsiDev.target->syncOffset != oldOffset ||
  851. !wasNeedSyncNegotiationAck) // Don't get into infinite loops negotiating.
  852. {
  853. scsiEnterPhase(MESSAGE_IN);
  854. uint8_t SDTR[] = {0x01, 0x03, 0x01, scsiDev.target->syncPeriod, scsiDev.target->syncOffset};
  855. scsiWrite(SDTR, sizeof(SDTR));
  856. scsiDev.needSyncNegotiationAck = 1; // Check if this message is rejected.
  857. scsiDev.sdUnderrunCount = 0; // reset counter, may work now.
  858. }
  859. }
  860. else
  861. {
  862. // Not supported
  863. messageReject();
  864. }
  865. }
  866. else
  867. {
  868. messageReject();
  869. }
  870. // Re-check the ATN flag in case it stays asserted.
  871. scsiDev.atnFlag |= scsiStatusATN();
  872. if (!scsiDev.atnFlag)
  873. {
  874. // Message wasn't rejected!
  875. scsiDev.needSyncNegotiationAck = 0;
  876. }
  877. }
  878. void scsiPoll(void)
  879. {
  880. if (resetUntil != 0 && resetUntil > s2s_getTime_ms())
  881. {
  882. return;
  883. }
  884. resetUntil = 0;
  885. if (unlikely(scsiDev.resetFlag))
  886. {
  887. scsiReset();
  888. // Still in reset phase for a few ms.
  889. // Do not try and process any commands.
  890. return;
  891. }
  892. switch (scsiDev.phase)
  893. {
  894. case BUS_FREE:
  895. if (scsiStatusBSY())
  896. {
  897. scsiDev.phase = BUS_BUSY;
  898. }
  899. // The Arbitration phase is optional for SCSI1/SASI hosts if there is only
  900. // one initiator in the chain. Support this by moving
  901. // straight to selection if SEL is asserted.
  902. // ie. the initiator won't assert BSY and it's own ID before moving to selection.
  903. else if (scsiDev.selFlag || *SCSI_STS_SELECTED)
  904. {
  905. enter_SelectionPhase();
  906. }
  907. break;
  908. case BUS_BUSY:
  909. // Someone is using the bus. Perhaps they are trying to
  910. // select us.
  911. if (scsiDev.selFlag || *SCSI_STS_SELECTED)
  912. {
  913. enter_SelectionPhase();
  914. }
  915. else if (!scsiStatusBSY())
  916. {
  917. scsiDev.phase = BUS_FREE;
  918. }
  919. break;
  920. case ARBITRATION:
  921. // TODO Support reselection.
  922. break;
  923. case SELECTION:
  924. process_SelectionPhase();
  925. break;
  926. case RESELECTION:
  927. // Not currently supported!
  928. break;
  929. case COMMAND:
  930. // Do not check ATN here. SCSI 1 & 2 initiators must set ATN
  931. // and SEL together upon entering the selection phase if they
  932. // want to send a message (IDENTIFY) immediately.
  933. if (scsiDev.atnFlag)
  934. {
  935. process_MessageOut();
  936. }
  937. else
  938. {
  939. process_Command();
  940. }
  941. break;
  942. case DATA_IN:
  943. scsiDev.atnFlag |= scsiStatusATN();
  944. if (scsiDev.atnFlag)
  945. {
  946. process_MessageOut();
  947. }
  948. else
  949. {
  950. process_DataIn();
  951. }
  952. break;
  953. case DATA_OUT:
  954. scsiDev.atnFlag |= scsiStatusATN();
  955. if (scsiDev.atnFlag)
  956. {
  957. process_MessageOut();
  958. }
  959. else
  960. {
  961. process_DataOut();
  962. }
  963. break;
  964. case STATUS:
  965. scsiDev.atnFlag |= scsiStatusATN();
  966. if (scsiDev.atnFlag)
  967. {
  968. process_MessageOut();
  969. }
  970. else
  971. {
  972. process_Status();
  973. }
  974. break;
  975. case MESSAGE_IN:
  976. scsiDev.atnFlag |= scsiStatusATN();
  977. if (scsiDev.atnFlag)
  978. {
  979. process_MessageOut();
  980. }
  981. else
  982. {
  983. process_MessageIn(1);
  984. }
  985. break;
  986. case MESSAGE_OUT:
  987. process_MessageOut();
  988. break;
  989. }
  990. }
  991. void scsiInit()
  992. {
  993. static int firstInit = 1;
  994. scsiDev.atnFlag = 0;
  995. scsiDev.resetFlag = 1;
  996. scsiDev.selFlag = 0;
  997. scsiDev.phase = BUS_FREE;
  998. scsiDev.target = NULL;
  999. scsiDev.compatMode = COMPAT_UNKNOWN;
  1000. int i;
  1001. for (i = 0; i < S2S_MAX_TARGETS; ++i)
  1002. {
  1003. const S2S_TargetCfg* cfg = s2s_getConfigByIndex(i);
  1004. if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED))
  1005. {
  1006. scsiDev.targets[i].targetId = cfg->scsiId & S2S_CFG_TARGET_ID_BITS;
  1007. scsiDev.targets[i].cfg = cfg;
  1008. scsiDev.targets[i].liveCfg.bytesPerSector = cfg->bytesPerSector;
  1009. }
  1010. else
  1011. {
  1012. scsiDev.targets[i].targetId = 0xff;
  1013. scsiDev.targets[i].cfg = NULL;
  1014. }
  1015. scsiDev.targets[i].reservedId = -1;
  1016. scsiDev.targets[i].reserverId = -1;
  1017. if (firstInit)
  1018. {
  1019. scsiDev.targets[i].unitAttention = POWER_ON_RESET;
  1020. }
  1021. else
  1022. {
  1023. scsiDev.targets[i].unitAttention = PARAMETERS_CHANGED;
  1024. }
  1025. scsiDev.targets[i].sense.code = NO_SENSE;
  1026. scsiDev.targets[i].sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;
  1027. scsiDev.targets[i].syncOffset = 0;
  1028. scsiDev.targets[i].syncPeriod = 0;
  1029. }
  1030. firstInit = 0;
  1031. }
  1032. /* TODO REENABLE
  1033. void scsiDisconnect()
  1034. {
  1035. scsiEnterPhase(MESSAGE_IN);
  1036. scsiWriteByte(0x02); // save data pointer
  1037. scsiWriteByte(0x04); // disconnect msg.
  1038. // For now, the caller is responsible for tracking the disconnected
  1039. // state, and calling scsiReconnect.
  1040. // Ideally the client would exit their loop and we'd implement this
  1041. // as part of scsiPoll
  1042. int phase = scsiDev.phase;
  1043. enter_BusFree();
  1044. scsiDev.phase = phase;
  1045. }
  1046. */
  1047. /* TODO REENABLE
  1048. int scsiReconnect()
  1049. {
  1050. int reconnected = 0;
  1051. int sel = SCSI_ReadFilt(SCSI_Filt_SEL);
  1052. int bsy = SCSI_ReadFilt(SCSI_Filt_BSY);
  1053. if (!sel && !bsy)
  1054. {
  1055. s2s_delay_us(1);
  1056. sel = SCSI_ReadFilt(SCSI_Filt_SEL);
  1057. bsy = SCSI_ReadFilt(SCSI_Filt_BSY);
  1058. }
  1059. if (!sel && !bsy)
  1060. {
  1061. // Arbitrate.
  1062. s2s_ledOn();
  1063. uint8_t scsiIdMask = 1 << scsiDev.target->targetId;
  1064. SCSI_Out_Bits_Write(scsiIdMask);
  1065. SCSI_Out_Ctl_Write(1); // Write bits manually.
  1066. SCSI_SetPin(SCSI_Out_BSY);
  1067. s2s_delay_us(3); // arbitrate delay. 2.4us.
  1068. uint8_t dbx = scsiReadDBxPins();
  1069. sel = SCSI_ReadFilt(SCSI_Filt_SEL);
  1070. if (sel || ((dbx ^ scsiIdMask) > scsiIdMask))
  1071. {
  1072. // Lost arbitration.
  1073. SCSI_Out_Ctl_Write(0);
  1074. SCSI_ClearPin(SCSI_Out_BSY);
  1075. s2s_ledOff();
  1076. }
  1077. else
  1078. {
  1079. // Won arbitration
  1080. SCSI_SetPin(SCSI_Out_SEL);
  1081. s2s_delay_us(1); // Bus clear + Bus settle.
  1082. // Reselection phase
  1083. SCSI_CTL_PHASE_Write(__scsiphase_io);
  1084. SCSI_Out_Bits_Write(scsiIdMask | (1 << scsiDev.initiatorId));
  1085. scsiDeskewDelay(); // 2 deskew delays
  1086. scsiDeskewDelay(); // 2 deskew delays
  1087. SCSI_ClearPin(SCSI_Out_BSY);
  1088. s2s_delay_us(1); // Bus Settle Delay
  1089. uint32_t waitStart_ms = getTime_ms();
  1090. bsy = SCSI_ReadFilt(SCSI_Filt_BSY);
  1091. // Wait for initiator.
  1092. while (
  1093. !bsy &&
  1094. !scsiDev.resetFlag &&
  1095. (elapsedTime_ms(waitStart_ms) < 250))
  1096. {
  1097. bsy = SCSI_ReadFilt(SCSI_Filt_BSY);
  1098. }
  1099. if (bsy)
  1100. {
  1101. SCSI_SetPin(SCSI_Out_BSY);
  1102. scsiDeskewDelay(); // 2 deskew delays
  1103. scsiDeskewDelay(); // 2 deskew delays
  1104. SCSI_ClearPin(SCSI_Out_SEL);
  1105. // Prepare for the initial IDENTIFY message.
  1106. SCSI_Out_Ctl_Write(0);
  1107. scsiEnterPhase(MESSAGE_IN);
  1108. // Send identify command
  1109. scsiWriteByte(0x80);
  1110. scsiEnterPhase(scsiDev.phase);
  1111. reconnected = 1;
  1112. }
  1113. else
  1114. {
  1115. // reselect timeout.
  1116. SCSI_Out_Ctl_Write(0);
  1117. SCSI_ClearPin(SCSI_Out_SEL);
  1118. SCSI_CTL_PHASE_Write(0);
  1119. s2s_ledOff();
  1120. }
  1121. }
  1122. }
  1123. return reconnected;
  1124. }
  1125. */