ArdSCSinoV2.ino 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290
  1. /*
  2. * BlueSCSI
  3. * Copyright (c) 2021 Eric Helgeson
  4. *
  5. * This file is free software: you may copy, redistribute and/or modify it
  6. * under the terms of the GNU General Public License as published by the
  7. * Free Software Foundation, either version 2 of the License, or (at your
  8. * option) any later version.
  9. *
  10. * This file is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see https://github.com/erichelgeson/bluescsi.
  17. *
  18. * This file incorporates work covered by the following copyright and
  19. * permission notice:
  20. *
  21. * Copyright (c) 2019 komatsu
  22. *
  23. * Permission to use, copy, modify, and/or distribute this software
  24. * for any purpose with or without fee is hereby granted, provided
  25. * that the above copyright notice and this permission notice appear
  26. * in all copies.
  27. *
  28. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  29. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  30. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  31. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
  32. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  33. * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  34. * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  35. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  36. */
  37. #include <Arduino.h> // For Platform.IO
  38. #include <SdFat.h>
  39. #ifdef USE_STM32_DMA
  40. #warning "warning USE_STM32_DMA"
  41. #endif
  42. #define DEBUG 0 // 0:No debug information output
  43. // 1: Debug information output available
  44. #define SCSI_SELECT 0 // 0 for STANDARD
  45. // 1 for SHARP X1turbo
  46. // 2 for NEC PC98
  47. #define READ_SPEED_OPTIMIZE 1 // Faster reads
  48. #define WRITE_SPEED_OPTIMIZE 1 // Speeding up writes
  49. #define USE_DB2ID_TABLE 1 // Use table to get ID from SEL-DB
  50. // SCSI config
  51. #define NUM_SCSIID 7 // Maximum number of supported SCSI-IDs (The minimum is 0)
  52. #define NUM_SCSILUN 2 // Maximum number of LUNs supported (The minimum is 0)
  53. #define READ_PARITY_CHECK 0 // Perform read parity check (unverified)
  54. // HDD format
  55. #define MAX_BLOCKSIZE 1024 // Maximum BLOCK size
  56. // SDFAT
  57. #define SD1_CONFIG SdSpiConfig(PA4, SHARED_SPI, SD_SCK_MHZ(SPI_FULL_SPEED), &SPI)
  58. SdFs SD;
  59. #if DEBUG
  60. #define LOG(XX) Serial.print(XX)
  61. #define LOGHEX(XX) Serial.print(XX, HEX)
  62. #define LOGN(XX) Serial.println(XX)
  63. #define LOGHEXN(XX) Serial.println(XX, HEX)
  64. #else
  65. #define LOG(XX) //Serial.print(XX)
  66. #define LOGHEX(XX) //Serial.print(XX, HEX)
  67. #define LOGN(XX) //Serial.println(XX)
  68. #define LOGHEXN(XX) //Serial.println(XX, HEX)
  69. #endif
  70. #define active 1
  71. #define inactive 0
  72. #define high 0
  73. #define low 1
  74. #define isHigh(XX) ((XX) == high)
  75. #define isLow(XX) ((XX) != high)
  76. #define gpio_mode(pin,val) gpio_set_mode(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, val);
  77. #define gpio_write(pin,val) gpio_write_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, val)
  78. #define gpio_read(pin) gpio_read_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit)
  79. //#define DB0 PB8 // SCSI:DB0
  80. //#define DB1 PB9 // SCSI:DB1
  81. //#define DB2 PB10 // SCSI:DB2
  82. //#define DB3 PB11 // SCSI:DB3
  83. //#define DB4 PB12 // SCSI:DB4
  84. //#define DB5 PB13 // SCSI:DB5
  85. //#define DB6 PB14 // SCSI:DB6
  86. //#define DB7 PB15 // SCSI:DB7
  87. //#define DBP PB0 // SCSI:DBP
  88. #define ATN PA8 // SCSI:ATN
  89. #define BSY PA9 // SCSI:BSY
  90. #define ACK PA10 // SCSI:ACK
  91. #define RST PA15 // SCSI:RST
  92. #define MSG PB3 // SCSI:MSG
  93. #define SEL PB4 // SCSI:SEL
  94. #define CD PB5 // SCSI:C/D
  95. #define REQ PB6 // SCSI:REQ
  96. #define IO PB7 // SCSI:I/O
  97. #define SD_CS PA4 // SDCARD:CS
  98. #define LED PC13 // LED
  99. // GPIO register port
  100. #define PAREG GPIOA->regs
  101. #define PBREG GPIOB->regs
  102. // LED control
  103. #define LED_ON() gpio_write(LED, high);
  104. #define LED_OFF() gpio_write(LED, low);
  105. // Virtual pin (Arduio compatibility is slow, so make it MCU-dependent)
  106. #define PA(BIT) (BIT)
  107. #define PB(BIT) (BIT+16)
  108. // Virtual pin decoding
  109. #define GPIOREG(VPIN) ((VPIN)>=16?PBREG:PAREG)
  110. #define BITMASK(VPIN) (1<<((VPIN)&15))
  111. #define vATN PA(8) // SCSI:ATN
  112. #define vBSY PA(9) // SCSI:BSY
  113. #define vACK PA(10) // SCSI:ACK
  114. #define vRST PA(15) // SCSI:RST
  115. #define vMSG PB(3) // SCSI:MSG
  116. #define vSEL PB(4) // SCSI:SEL
  117. #define vCD PB(5) // SCSI:C/D
  118. #define vREQ PB(6) // SCSI:REQ
  119. #define vIO PB(7) // SCSI:I/O
  120. #define vSD_CS PA(4) // SDCARD:CS
  121. // SCSI output pin control: opendrain active LOW (direct pin drive)
  122. #define SCSI_OUT(VPIN,ACTIVE) { GPIOREG(VPIN)->BSRR = BITMASK(VPIN)<<((ACTIVE)?16:0); }
  123. // SCSI input pin check (inactive=0,avtive=1)
  124. #define SCSI_IN(VPIN) ((~GPIOREG(VPIN)->IDR>>(VPIN&15))&1)
  125. // GPIO mode
  126. // IN , FLOAT : 4
  127. // IN , PU/PD : 8
  128. // OUT, PUSH/PULL : 3
  129. // OUT, OD : 1
  130. //#define DB_MODE_OUT 3
  131. #define DB_MODE_OUT 1
  132. #define DB_MODE_IN 8
  133. // Put DB and DP in output mode
  134. #define SCSI_DB_OUTPUT() { PBREG->CRL=(PBREG->CRL &0xfffffff0)|DB_MODE_OUT; PBREG->CRH = 0x11111111*DB_MODE_OUT; }
  135. // Put DB and DP in input mode
  136. #define SCSI_DB_INPUT() { PBREG->CRL=(PBREG->CRL &0xfffffff0)|DB_MODE_IN ; PBREG->CRH = 0x11111111*DB_MODE_IN; }
  137. // Turn on the output only for BSY
  138. #define SCSI_BSY_ACTIVE() { gpio_mode(BSY, GPIO_OUTPUT_OD); SCSI_OUT(vBSY, active) }
  139. // BSY,REQ,MSG,CD,IO Turn on the output (no change required for OD)
  140. #define SCSI_TARGET_ACTIVE() { }
  141. // BSY,REQ,MSG,CD,IO Turn off output, BSY is the last input
  142. #define SCSI_TARGET_INACTIVE() { SCSI_OUT(vREQ,inactive); SCSI_OUT(vMSG,inactive); SCSI_OUT(vCD,inactive);SCSI_OUT(vIO,inactive); SCSI_OUT(vBSY,inactive); gpio_mode(BSY, GPIO_INPUT_PU); }
  143. // HDDiamge file
  144. #define HDIMG_FILE_256 "HDxx_256.HDS" // BLOCKSIZE=256 のHDDイメージファイル
  145. #define HDIMG_FILE_512 "HDxx_512.HDS" // BLOCKSIZE=512 のHDDイメージファイル名ベース
  146. #define HDIMG_FILE_1024 "HDxx_1024.HDS" // BLOCKSIZE=1024 のHDDイメージファイル
  147. #define HDIMG_ID_POS 2 // ID数字を埋め込む位置
  148. #define HDIMG_LUN_POS 3 // LUN数字を埋め込む位置
  149. #define MAX_FILE_PATH 32 // 最大ファイル名長
  150. // HDD image
  151. typedef struct hddimg_struct
  152. {
  153. FsFile m_file; // File object
  154. uint64_t m_fileSize; // File size
  155. size_t m_blocksize; // SCSI BLOCK size
  156. }HDDIMG;
  157. HDDIMG img[NUM_SCSIID][NUM_SCSILUN]; // Maximum number
  158. uint8_t m_senseKey = 0; // Sense key
  159. volatile bool m_isBusReset = false; // Bus reset
  160. byte scsi_id_mask; // Mask list of responding SCSI IDs
  161. byte m_id; // Currently responding SCSI-ID
  162. byte m_lun; // Logical unit number currently responding
  163. byte m_sts; // Status byte
  164. byte m_msg; // Message bytes
  165. HDDIMG *m_img; // HDD image for current SCSI-ID, LUN
  166. byte m_buf[MAX_BLOCKSIZE+1]; // General purpose buffer + overrun fetch
  167. int m_msc;
  168. bool m_msb[256];
  169. /*
  170. * Data byte to BSRR register setting value and parity table
  171. */
  172. // Parity bit generation
  173. #define PTY(V) (1^((V)^((V)>>1)^((V)>>2)^((V)>>3)^((V)>>4)^((V)>>5)^((V)>>6)^((V)>>7))&1)
  174. // Data byte to BSRR register setting value conversion table
  175. // BSRR[31:24] = DB[7:0]
  176. // BSRR[ 16] = PTY(DB)
  177. // BSRR[15: 8] = ~DB[7:0]
  178. // BSRR[ 0] = ~PTY(DB)
  179. // Set DBP, set REQ = inactive
  180. #define DBP(D) ((((((uint32_t)(D)<<8)|PTY(D))*0x00010001)^0x0000ff01)|BITMASK(vREQ))
  181. #define DBP8(D) DBP(D),DBP(D+1),DBP(D+2),DBP(D+3),DBP(D+4),DBP(D+5),DBP(D+6),DBP(D+7)
  182. #define DBP32(D) DBP8(D),DBP8(D+8),DBP8(D+16),DBP8(D+24)
  183. // BSRR register control value that simultaneously performs DB set, DP set, and REQ = H (inactrive)
  184. static const uint32_t db_bsrr[256]={
  185. DBP32(0x00),DBP32(0x20),DBP32(0x40),DBP32(0x60),
  186. DBP32(0x80),DBP32(0xA0),DBP32(0xC0),DBP32(0xE0)
  187. };
  188. // Parity bit acquisition
  189. #define PARITY(DB) (db_bsrr[DB]&1)
  190. // Macro cleaning
  191. #undef DBP32
  192. #undef DBP8
  193. //#undef DBP
  194. //#undef PTY
  195. #if USE_DB2ID_TABLE
  196. /* DB to SCSI-ID translation table */
  197. static const byte db2scsiid[256]={
  198. 0xff,
  199. 0,
  200. 1,1,
  201. 2,2,2,2,
  202. 3,3,3,3,3,3,3,3,
  203. 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
  204. 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
  205. 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
  206. 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
  207. 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  208. 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  209. 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  210. 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
  211. };
  212. #endif
  213. // Log File
  214. #define VERSION "1.0-b"
  215. #define LOG_FILENAME "LOG.txt"
  216. FsFile LOG_FILE;
  217. void onFalseInit(void);
  218. void onBusReset(void);
  219. /*
  220. * IO read.
  221. */
  222. inline byte readIO(void)
  223. {
  224. // Port input data register
  225. uint32_t ret = GPIOB->regs->IDR;
  226. byte bret = (byte)((~ret)>>8);
  227. #if READ_PARITY_CHECK
  228. if((db_bsrr[bret]^ret)&1)
  229. m_sts |= 0x01; // parity error
  230. #endif
  231. return bret;
  232. }
  233. /*
  234. * HDDイメージファイルのオープン
  235. */
  236. bool hddimageOpen(HDDIMG *h,const char *image_name,int id,int lun,int blocksize)
  237. {
  238. char file_path[MAX_FILE_PATH+1];
  239. // build file path
  240. strcpy(file_path,image_name);
  241. file_path[HDIMG_ID_POS ] = '0'+id;
  242. file_path[HDIMG_LUN_POS] = '0'+lun;
  243. h->m_fileSize = 0;
  244. h->m_blocksize = blocksize;
  245. h->m_file = SD.open(file_path, O_RDWR);
  246. if(h->m_file.isOpen())
  247. {
  248. h->m_fileSize = h->m_file.size();
  249. LOG_FILE.print("Imagefile: ");
  250. LOG_FILE.print(file_path);
  251. if(h->m_fileSize>0)
  252. {
  253. // check blocksize dummy file
  254. LOG_FILE.print(" / ");
  255. LOG_FILE.print(h->m_fileSize);
  256. LOG_FILE.print("bytes / ");
  257. LOG_FILE.print(h->m_fileSize / 1024);
  258. LOG_FILE.print("KiB / ");
  259. LOG_FILE.print(h->m_fileSize / 1024 / 1024);
  260. LOG_FILE.println("MiB");
  261. return true; // File opened
  262. }
  263. else
  264. {
  265. h->m_file.close();
  266. h->m_fileSize = h->m_blocksize = 0; // no file
  267. LOG_FILE.println("FileSizeError");
  268. }
  269. }
  270. return false;
  271. }
  272. /*
  273. * Initialization.
  274. * Initialize the bus and set the PIN orientation
  275. */
  276. void setup()
  277. {
  278. // PA15 / PB3 / PB4 Cannot be used
  279. // JTAG Because it is used for debugging.
  280. disableDebugPorts();
  281. // Serial initialization
  282. #if DEBUG
  283. Serial.begin(9600);
  284. while (!Serial);
  285. #endif
  286. // PIN initialization
  287. gpio_mode(LED, GPIO_OUTPUT_OD);
  288. gpio_write(LED, low);
  289. //GPIO(SCSI BUS)Initialization
  290. //Port setting register (lower)
  291. // GPIOB->regs->CRL |= 0x000000008; // SET INPUT W/ PUPD on PAB-PB0
  292. //Port setting register (upper)
  293. //GPIOB->regs->CRH = 0x88888888; // SET INPUT W/ PUPD on PB15-PB8
  294. // GPIOB->regs->ODR = 0x0000FF00; // SET PULL-UPs on PB15-PB8
  295. // DB,DPは入力モード
  296. SCSI_DB_INPUT()
  297. // Input port
  298. gpio_mode(ATN, GPIO_INPUT_PU);
  299. gpio_mode(BSY, GPIO_INPUT_PU);
  300. gpio_mode(ACK, GPIO_INPUT_PU);
  301. gpio_mode(RST, GPIO_INPUT_PU);
  302. gpio_mode(SEL, GPIO_INPUT_PU);
  303. // Output port
  304. gpio_mode(MSG, GPIO_OUTPUT_OD);
  305. gpio_mode(CD, GPIO_OUTPUT_OD);
  306. gpio_mode(REQ, GPIO_OUTPUT_OD);
  307. gpio_mode(IO, GPIO_OUTPUT_OD);
  308. // Turn off the output port
  309. SCSI_TARGET_INACTIVE()
  310. //RSTピンの状態がHIGHからLOWに変わったときに発生
  311. //attachInterrupt(PIN_MAP[RST].gpio_bit, onBusReset, FALLING);
  312. LED_ON();
  313. // clock = 36MHz , about 4Mbytes/sec
  314. if(!SD.begin(SD1_CONFIG)) {
  315. #if DEBUG
  316. Serial.println("SD initialization failed!");
  317. #endif
  318. onFalseInit();
  319. }
  320. initFileLog();
  321. //Sector data overrun byte setting
  322. m_buf[MAX_BLOCKSIZE] = 0xff; // DB0 all off,DBP off
  323. //HD image file open
  324. scsi_id_mask = 0x00;
  325. for(int id=0;id<NUM_SCSIID;id++)
  326. {
  327. for(int lun=0;lun<NUM_SCSILUN;lun++)
  328. {
  329. HDDIMG *h = &img[id][lun];
  330. bool imageReady = false;
  331. if(!imageReady)
  332. {
  333. imageReady = hddimageOpen(h,HDIMG_FILE_256,id,lun,256);
  334. }
  335. if(!imageReady)
  336. {
  337. imageReady = hddimageOpen(h,HDIMG_FILE_512,id,lun,512);
  338. }
  339. if(!imageReady)
  340. {
  341. imageReady = hddimageOpen(h,HDIMG_FILE_1024,id,lun, 1024);
  342. }
  343. if(imageReady)
  344. {
  345. // Marked as a responsive ID
  346. scsi_id_mask |= 1<<id;
  347. }
  348. }
  349. }
  350. // Error if there are 0 image files
  351. if(scsi_id_mask==0) onFalseInit();
  352. finalizeFileLog();
  353. LED_OFF();
  354. //Occurs when the RST pin state changes from HIGH to LOW
  355. attachInterrupt(PIN_MAP[RST].gpio_bit, onBusReset, FALLING);
  356. }
  357. /*
  358. * Setup initialization logfile
  359. */
  360. void initFileLog() {
  361. LOG_FILE = SD.open(LOG_FILENAME, O_WRONLY | O_CREAT);
  362. LOG_FILE.print("VERSION: ");
  363. LOG_FILE.println(VERSION);
  364. LOG_FILE.println("Initialized SD Card - lets go!");
  365. }
  366. /*
  367. * Finalize initialization logfile
  368. */
  369. void finalizeFileLog() {
  370. // View support drive map
  371. LOG_FILE.print("ID");
  372. for(int lun=0;lun<NUM_SCSILUN;lun++)
  373. {
  374. LOG_FILE.print(":LUN");
  375. LOG_FILE.print(lun);
  376. }
  377. LOG_FILE.println(":");
  378. //
  379. for(int id=0;id<NUM_SCSIID;id++)
  380. {
  381. LOG_FILE.print(" ");
  382. LOG_FILE.print(id);
  383. for(int lun=0;lun<NUM_SCSILUN;lun++)
  384. {
  385. HDDIMG *h = &img[id][lun];
  386. if( (lun<NUM_SCSILUN) && (h->m_file))
  387. {
  388. LOG_FILE.print((h->m_blocksize<1000) ? ": " : ":");
  389. LOG_FILE.print(h->m_blocksize);
  390. }
  391. else
  392. LOG_FILE.print(":----");
  393. }
  394. LOG_FILE.println(":");
  395. }
  396. LOG_FILE.println("Finished initialization of SCSI Devices - Entering main loop.");
  397. LOG_FILE.sync();
  398. LOG_FILE.close();
  399. }
  400. /*
  401. * Initialization failed.
  402. */
  403. void onFalseInit(void)
  404. {
  405. while(true) {
  406. gpio_write(LED, high);
  407. delay(500);
  408. gpio_write(LED, low);
  409. delay(500);
  410. }
  411. }
  412. /*
  413. * Bus reset interrupt.
  414. */
  415. void onBusReset(void)
  416. {
  417. #if SCSI_SELECT == 1
  418. // SASI I / F for X1 turbo has RST pulse write cycle +2 clock ==
  419. // I can't filter because it only activates about 1.25us
  420. {{
  421. #else
  422. if(isHigh(gpio_read(RST))) {
  423. delayMicroseconds(20);
  424. if(isHigh(gpio_read(RST))) {
  425. #endif
  426. // BUS FREE is done in the main process
  427. // gpio_mode(MSG, GPIO_OUTPUT_OD);
  428. // gpio_mode(CD, GPIO_OUTPUT_OD);
  429. // gpio_mode(REQ, GPIO_OUTPUT_OD);
  430. // gpio_mode(IO, GPIO_OUTPUT_OD);
  431. // Should I enter DB and DBP once?
  432. SCSI_DB_INPUT()
  433. LOGN("BusReset!");
  434. m_isBusReset = true;
  435. }
  436. }
  437. }
  438. /*
  439. * Read by handshake.
  440. */
  441. inline byte readHandshake(void)
  442. {
  443. SCSI_OUT(vREQ,active)
  444. //SCSI_DB_INPUT()
  445. while(!SCSI_IN(vACK)) { if(m_isBusReset) return 0; }
  446. byte r = readIO();
  447. SCSI_OUT(vREQ,inactive)
  448. while( SCSI_IN(vACK)) { if(m_isBusReset) return 0; }
  449. return r;
  450. }
  451. /*
  452. * Write with a handshake.
  453. */
  454. inline void writeHandshake(byte d)
  455. {
  456. GPIOB->regs->BSRR = db_bsrr[d]; // setup DB,DBP (160ns)
  457. SCSI_DB_OUTPUT() // (180ns)
  458. // ACK.Fall to DB output delay 100ns(MAX) (DTC-510B)
  459. SCSI_OUT(vREQ,inactive) // setup wait (30ns)
  460. SCSI_OUT(vREQ,inactive) // setup wait (30ns)
  461. SCSI_OUT(vREQ,inactive) // setup wait (30ns)
  462. SCSI_OUT(vREQ,active) // (30ns)
  463. //while(!SCSI_IN(vACK)) { if(m_isBusReset){ SCSI_DB_INPUT() return; }}
  464. while(!m_isBusReset && !SCSI_IN(vACK));
  465. // ACK.Fall to REQ.Raise delay 500ns(typ.) (DTC-510B)
  466. GPIOB->regs->BSRR = DBP(0xff); // DB=0xFF , SCSI_OUT(vREQ,inactive)
  467. // REQ.Raise to DB hold time 0ns
  468. SCSI_DB_INPUT() // (150ns)
  469. while( SCSI_IN(vACK)) { if(m_isBusReset) return; }
  470. }
  471. /*
  472. * Data in phase.
  473. * Send len bytes of data array p.
  474. */
  475. void writeDataPhase(int len, const byte* p)
  476. {
  477. LOGN("DATAIN PHASE");
  478. SCSI_OUT(vMSG,inactive) // gpio_write(MSG, low);
  479. SCSI_OUT(vCD ,inactive) // gpio_write(CD, low);
  480. SCSI_OUT(vIO , active) // gpio_write(IO, high);
  481. for (int i = 0; i < len; i++) {
  482. if(m_isBusReset) {
  483. return;
  484. }
  485. writeHandshake(p[i]);
  486. }
  487. }
  488. /*
  489. * Data in phase.
  490. * Send len block while reading from SD card.
  491. */
  492. void writeDataPhaseSD(uint32_t adds, uint32_t len)
  493. {
  494. LOGN("DATAIN PHASE(SD)");
  495. uint32_t pos = adds * m_img->m_blocksize;
  496. m_img->m_file.seek(pos);
  497. SCSI_OUT(vMSG,inactive) // gpio_write(MSG, low);
  498. SCSI_OUT(vCD ,inactive) // gpio_write(CD, low);
  499. SCSI_OUT(vIO , active) // gpio_write(IO, high);
  500. for(uint32_t i = 0; i < len; i++) {
  501. // Asynchronous reads will make it faster ...
  502. m_img->m_file.read(m_buf, m_img->m_blocksize);
  503. #if READ_SPEED_OPTIMIZE
  504. //#define REQ_ON() SCSI_OUT(vREQ,active)
  505. #define REQ_ON() (*db_dst = BITMASK(vREQ)<<16)
  506. #define FETCH_SRC() (src_byte = *srcptr++)
  507. #define FETCH_BSRR_DB() (bsrr_val = bsrr_tbl[src_byte])
  508. #define REQ_OFF_DB_SET(BSRR_VAL) *db_dst = BSRR_VAL
  509. #define WAIT_ACK_ACTIVE() while(!m_isBusReset && !SCSI_IN(vACK))
  510. #define WAIT_ACK_INACTIVE() do{ if(m_isBusReset) return; }while(SCSI_IN(vACK))
  511. SCSI_DB_OUTPUT()
  512. register byte *srcptr= m_buf; // Source buffer
  513. register byte *endptr= m_buf + m_img->m_blocksize; // 終了ポインタ
  514. /*register*/ byte src_byte; // Send data bytes
  515. register const uint32_t *bsrr_tbl = db_bsrr; // Table to convert to BSRR
  516. register uint32_t bsrr_val; // BSRR value to output (DB, DBP, REQ = ACTIVE)
  517. register volatile uint32_t *db_dst = &(GPIOB->regs->BSRR); // Output port
  518. // prefetch & 1st out
  519. FETCH_SRC();
  520. FETCH_BSRR_DB();
  521. REQ_OFF_DB_SET(bsrr_val);
  522. // DB.set to REQ.F setup 100ns max (DTC-510B)
  523. // Maybe there should be some weight here
  524. // WAIT_ACK_INACTIVE();
  525. do{
  526. // 0
  527. REQ_ON();
  528. FETCH_SRC();
  529. FETCH_BSRR_DB();
  530. WAIT_ACK_ACTIVE();
  531. // ACK.F to REQ.R 500ns typ. (DTC-510B)
  532. REQ_OFF_DB_SET(bsrr_val);
  533. WAIT_ACK_INACTIVE();
  534. // 1
  535. REQ_ON();
  536. FETCH_SRC();
  537. FETCH_BSRR_DB();
  538. WAIT_ACK_ACTIVE();
  539. REQ_OFF_DB_SET(bsrr_val);
  540. WAIT_ACK_INACTIVE();
  541. // 2
  542. REQ_ON();
  543. FETCH_SRC();
  544. FETCH_BSRR_DB();
  545. WAIT_ACK_ACTIVE();
  546. REQ_OFF_DB_SET(bsrr_val);
  547. WAIT_ACK_INACTIVE();
  548. // 3
  549. REQ_ON();
  550. FETCH_SRC();
  551. FETCH_BSRR_DB();
  552. WAIT_ACK_ACTIVE();
  553. REQ_OFF_DB_SET(bsrr_val);
  554. WAIT_ACK_INACTIVE();
  555. // 4
  556. REQ_ON();
  557. FETCH_SRC();
  558. FETCH_BSRR_DB();
  559. WAIT_ACK_ACTIVE();
  560. REQ_OFF_DB_SET(bsrr_val);
  561. WAIT_ACK_INACTIVE();
  562. // 5
  563. REQ_ON();
  564. FETCH_SRC();
  565. FETCH_BSRR_DB();
  566. WAIT_ACK_ACTIVE();
  567. REQ_OFF_DB_SET(bsrr_val);
  568. WAIT_ACK_INACTIVE();
  569. // 6
  570. REQ_ON();
  571. FETCH_SRC();
  572. FETCH_BSRR_DB();
  573. WAIT_ACK_ACTIVE();
  574. REQ_OFF_DB_SET(bsrr_val);
  575. WAIT_ACK_INACTIVE();
  576. // 7
  577. REQ_ON();
  578. FETCH_SRC();
  579. FETCH_BSRR_DB();
  580. WAIT_ACK_ACTIVE();
  581. REQ_OFF_DB_SET(bsrr_val);
  582. WAIT_ACK_INACTIVE();
  583. }while(srcptr < endptr);
  584. SCSI_DB_INPUT()
  585. #else
  586. for(int j = 0; j < BLOCKSIZE; j++) {
  587. if(m_isBusReset) {
  588. return;
  589. }
  590. writeHandshake(m_buf[j]);
  591. }
  592. #endif
  593. }
  594. }
  595. /*
  596. * Data out phase.
  597. * len block read
  598. */
  599. void readDataPhase(int len, byte* p)
  600. {
  601. LOGN("DATAOUT PHASE");
  602. SCSI_OUT(vMSG,inactive) // gpio_write(MSG, low);
  603. SCSI_OUT(vCD ,inactive) // gpio_write(CD, low);
  604. SCSI_OUT(vIO ,inactive) // gpio_write(IO, low);
  605. for(uint32_t i = 0; i < len; i++)
  606. p[i] = readHandshake();
  607. }
  608. /*
  609. * Data out phase.
  610. * Write to SD card while reading len block.
  611. */
  612. void readDataPhaseSD(uint32_t adds, uint32_t len)
  613. {
  614. LOGN("DATAOUT PHASE(SD)");
  615. uint32_t pos = adds * m_img->m_blocksize;
  616. m_img->m_file.seek(pos);
  617. SCSI_OUT(vMSG,inactive) // gpio_write(MSG, low);
  618. SCSI_OUT(vCD ,inactive) // gpio_write(CD, low);
  619. SCSI_OUT(vIO ,inactive) // gpio_write(IO, low);
  620. for(uint32_t i = 0; i < len; i++) {
  621. #if WRITE_SPEED_OPTIMIZE
  622. register byte *dstptr= m_buf;
  623. register byte *endptr= m_buf + m_img->m_blocksize;
  624. for(dstptr=m_buf;dstptr<endptr;dstptr+=8) {
  625. dstptr[0] = readHandshake();
  626. dstptr[1] = readHandshake();
  627. dstptr[2] = readHandshake();
  628. dstptr[3] = readHandshake();
  629. dstptr[4] = readHandshake();
  630. dstptr[5] = readHandshake();
  631. dstptr[6] = readHandshake();
  632. dstptr[7] = readHandshake();
  633. if(m_isBusReset) {
  634. return;
  635. }
  636. }
  637. #else
  638. for(int j = 0; j < m_img->m_blocksize; j++) {
  639. if(m_isBusReset) {
  640. return;
  641. }
  642. m_buf[j] = readHandshake();
  643. }
  644. #endif
  645. m_img->m_file.write(m_buf, m_img->m_blocksize);
  646. }
  647. m_img->m_file.flush();
  648. }
  649. /*
  650. * INQUIRY command processing.
  651. */
  652. #if SCSI_SELECT == 2
  653. byte onInquiryCommand(byte len)
  654. {
  655. byte buf[36] = {
  656. 0x00, //デバイスタイプ
  657. 0x00, //RMB = 0
  658. 0x01, //ISO,ECMA,ANSIバージョン
  659. 0x01, //レスポンスデータ形式
  660. 35 - 4, //追加データ長
  661. 0, 0, //Reserve
  662. 0x00, //サポート機能
  663. 'N', 'E', 'C', 'I', 'T', 'S', 'U', ' ',
  664. 'A', 'r', 'd', 'S', 'C', 'S', 'i', 'n', 'o', ' ', ' ',' ', ' ', ' ', ' ', ' ',
  665. '0', '0', '1', '0',
  666. };
  667. writeDataPhase(len < 36 ? len : 36, buf);
  668. return 0x00;
  669. }
  670. #else
  671. byte onInquiryCommand(byte len)
  672. {
  673. byte buf[36] = {
  674. 0x00, //device type
  675. 0x00, //RMB = 0
  676. 0x01, //ISO, ECMA, ANSI version
  677. 0x01, //Response data format
  678. 35 - 4, //Additional data length
  679. 0, 0, //Reserve
  680. 0x00, //Support function
  681. 'Q', 'U', 'A', 'N', 'T', 'U', 'M', ' ',
  682. 'F', 'I', 'R', 'E', 'B', 'A', 'L', 'L', '1', ' ', ' ',' ', ' ', ' ', ' ', ' ',
  683. '1', '.', '0', ' ',
  684. };
  685. writeDataPhase(len < 36 ? len : 36, buf);
  686. return 0x00;
  687. }
  688. #endif
  689. /*
  690. * REQUEST SENSE command processing.
  691. */
  692. void onRequestSenseCommand(byte len)
  693. {
  694. byte buf[18] = {
  695. 0x70, //CheckCondition
  696. 0, //Segment number
  697. 0x00, //Sense key
  698. 0, 0, 0, 0, //information
  699. 17 - 7 , //Additional data length
  700. 0,
  701. };
  702. buf[2] = m_senseKey;
  703. m_senseKey = 0;
  704. writeDataPhase(len < 18 ? len : 18, buf);
  705. }
  706. /*
  707. * READ CAPACITY command processing.
  708. */
  709. byte onReadCapacityCommand(byte pmi)
  710. {
  711. if(!m_img) return 0x02; // Image file absent
  712. uint32_t bl = m_img->m_blocksize;
  713. uint32_t bc = m_img->m_fileSize / bl;
  714. uint8_t buf[8] = {
  715. bc >> 24, bc >> 16, bc >> 8, bc,
  716. bl >> 24, bl >> 16, bl >> 8, bl
  717. };
  718. writeDataPhase(8, buf);
  719. return 0x00;
  720. }
  721. /*
  722. * READ6 / 10 Command processing.
  723. */
  724. byte onReadCommand(uint32_t adds, uint32_t len)
  725. {
  726. LOGN("-R");
  727. LOGHEXN(adds);
  728. LOGHEXN(len);
  729. if(!m_img) return 0x02; // Image file absent
  730. gpio_write(LED, high);
  731. writeDataPhaseSD(adds, len);
  732. gpio_write(LED, low);
  733. return 0x00; //sts
  734. }
  735. /*
  736. * WRITE6 / 10 Command processing.
  737. */
  738. byte onWriteCommand(uint32_t adds, uint32_t len)
  739. {
  740. LOGN("-W");
  741. LOGHEXN(adds);
  742. LOGHEXN(len);
  743. if(!m_img) return 0x02; // Image file absent
  744. gpio_write(LED, high);
  745. readDataPhaseSD(adds, len);
  746. gpio_write(LED, low);
  747. return 0; //sts
  748. }
  749. /*
  750. * MODE SENSE command processing.
  751. */
  752. #if SCSI_SELECT == 2
  753. byte onModeSenseCommand(byte dbd, int cmd2, uint32_t len)
  754. {
  755. if(!m_img) return 0x02; // Image file absent
  756. int pageCode = cmd2 & 0x3F;
  757. // デフォルト設定としてセクタサイズ512,セクタ数25,ヘッド数8を想定
  758. int size = m_img->m_fileSize;
  759. int cylinders = (int)(size >> 9);
  760. cylinders >>= 3;
  761. cylinders /= 25;
  762. int sectorsize = 512;
  763. int sectors = 25;
  764. int heads = 8;
  765. // セクタサイズ
  766. int disksize = 0;
  767. for(disksize = 16; disksize > 0; --(disksize)) {
  768. if ((1 << disksize) == sectorsize)
  769. break;
  770. }
  771. // ブロック数
  772. uint32_t diskblocks = (uint32_t)(size >> disksize);
  773. memset(m_buf, 0, sizeof(m_buf));
  774. int a = 4;
  775. if(dbd == 0) {
  776. uint32_t bl = m_img->m_blocksize;
  777. uint32_t bc = m_img->m_fileSize / bl;
  778. byte c[8] = {
  779. 0,//デンシティコード
  780. bc >> 16, bc >> 8, bc,
  781. 0, //Reserve
  782. bl >> 16, bl >> 8, bl
  783. };
  784. memcpy(&m_buf[4], c, 8);
  785. a += 8;
  786. m_buf[3] = 0x08;
  787. }
  788. switch(pageCode) {
  789. case 0x3F:
  790. {
  791. m_buf[a + 0] = 0x01;
  792. m_buf[a + 1] = 0x06;
  793. a += 8;
  794. }
  795. case 0x03: //ドライブパラメータ
  796. {
  797. m_buf[a + 0] = 0x80 | 0x03; //ページコード
  798. m_buf[a + 1] = 0x16; // ページ長
  799. m_buf[a + 2] = (byte)(heads >> 8);//セクタ数/トラック
  800. m_buf[a + 3] = (byte)(heads);//セクタ数/トラック
  801. m_buf[a + 10] = (byte)(sectors >> 8);//セクタ数/トラック
  802. m_buf[a + 11] = (byte)(sectors);//セクタ数/トラック
  803. int size = 1 << disksize;
  804. m_buf[a + 12] = (byte)(size >> 8);//セクタ数/トラック
  805. m_buf[a + 13] = (byte)(size);//セクタ数/トラック
  806. a += 24;
  807. if(pageCode != 0x3F) {
  808. break;
  809. }
  810. }
  811. case 0x04: //ドライブパラメータ
  812. {
  813. LOGN("AddDrive");
  814. m_buf[a + 0] = 0x04; //ページコード
  815. m_buf[a + 1] = 0x12; // ページ長
  816. m_buf[a + 2] = (cylinders >> 16);// シリンダ長
  817. m_buf[a + 3] = (cylinders >> 8);
  818. m_buf[a + 4] = cylinders;
  819. m_buf[a + 5] = heads; //ヘッド数
  820. a += 20;
  821. if(pageCode != 0x3F) {
  822. break;
  823. }
  824. }
  825. default:
  826. break;
  827. }
  828. m_buf[0] = a - 1;
  829. writeDataPhase(len < a ? len : a, m_buf);
  830. return 0x00;
  831. }
  832. #else
  833. byte onModeSenseCommand(byte dbd, int cmd2, uint32_t len)
  834. {
  835. if(!m_img) return 0x02; // イメージファイル不在
  836. memset(m_buf, 0, sizeof(m_buf));
  837. int pageCode = cmd2 & 0x3F;
  838. int a = 4;
  839. if(dbd == 0) {
  840. uint32_t bl = m_img->m_blocksize;
  841. uint32_t bc = m_img->m_fileSize / bl;
  842. byte c[8] = {
  843. 0,//Density code
  844. bc >> 16, bc >> 8, bc,
  845. 0, //Reserve
  846. bl >> 16, bl >> 8, bl
  847. };
  848. memcpy(&m_buf[4], c, 8);
  849. a += 8;
  850. m_buf[3] = 0x08;
  851. }
  852. switch(pageCode) {
  853. case 0x3F:
  854. case 0x03: //Drive parameters
  855. m_buf[a + 0] = 0x03; //Page code
  856. m_buf[a + 1] = 0x16; // Page length
  857. m_buf[a + 11] = 0x3F;//Number of sectors / track
  858. a += 24;
  859. if(pageCode != 0x3F) {
  860. break;
  861. }
  862. case 0x04: //Drive parameters
  863. {
  864. uint32_t bc = m_img->m_fileSize / m_img->m_file;
  865. m_buf[a + 0] = 0x04; //Page code
  866. m_buf[a + 1] = 0x16; // Page length
  867. m_buf[a + 2] = bc >> 16;// Cylinder length
  868. m_buf[a + 3] = bc >> 8;
  869. m_buf[a + 4] = bc;
  870. m_buf[a + 5] = 1; //Number of heads
  871. a += 24;
  872. }
  873. if(pageCode != 0x3F) {
  874. break;
  875. }
  876. default:
  877. break;
  878. }
  879. m_buf[0] = a - 1;
  880. writeDataPhase(len < a ? len : a, m_buf);
  881. return 0x00;
  882. }
  883. #endif
  884. #if SCSI_SELECT == 1
  885. /*
  886. * dtc510b_setDriveparameter
  887. */
  888. #define PACKED __attribute__((packed))
  889. typedef struct PACKED dtc500_cmd_c2_param_struct
  890. {
  891. uint8_t StepPlusWidth; // Default is 13.6usec (11)
  892. uint8_t StepPeriod; // Default is 3 msec.(60)
  893. uint8_t StepMode; // Default is Bufferd (0)
  894. uint8_t MaximumHeadAdress; // Default is 4 heads (3)
  895. uint8_t HighCylinderAddressByte; // Default set to 0 (0)
  896. uint8_t LowCylinderAddressByte; // Default is 153 cylinders (152)
  897. uint8_t ReduceWrietCurrent; // Default is above Cylinder 128 (127)
  898. uint8_t DriveType_SeekCompleteOption;// (0)
  899. uint8_t Reserved8; // (0)
  900. uint8_t Reserved9; // (0)
  901. } DTC510_CMD_C2_PARAM;
  902. static void logStrHex(const char *msg,uint32_t num)
  903. {
  904. LOG(msg);
  905. LOGHEXN(num);
  906. }
  907. static byte dtc510b_setDriveparameter(void)
  908. {
  909. DTC510_CMD_C2_PARAM DriveParameter;
  910. uint16_t maxCylinder;
  911. uint16_t numLAD;
  912. //uint32_t stepPulseUsec;
  913. int StepPeriodMsec;
  914. // receive paramter
  915. writeDataPhase(sizeof(DriveParameter),(byte *)(&DriveParameter));
  916. maxCylinder =
  917. (((uint16_t)DriveParameter.HighCylinderAddressByte)<<8) |
  918. (DriveParameter.LowCylinderAddressByte);
  919. numLAD = maxCylinder * (DriveParameter.MaximumHeadAdress+1);
  920. //stepPulseUsec = calcStepPulseUsec(DriveParameter.StepPlusWidth);
  921. StepPeriodMsec = DriveParameter.StepPeriod*50;
  922. logStrHex (" StepPlusWidth : ",DriveParameter.StepPlusWidth);
  923. logStrHex (" StepPeriod : ",DriveParameter.StepPeriod );
  924. logStrHex (" StepMode : ",DriveParameter.StepMode );
  925. logStrHex (" MaximumHeadAdress : ",DriveParameter.MaximumHeadAdress);
  926. logStrHex (" CylinderAddress : ",maxCylinder);
  927. logStrHex (" ReduceWrietCurrent : ",DriveParameter.ReduceWrietCurrent);
  928. logStrHex (" DriveType/SeekCompleteOption : ",DriveParameter.DriveType_SeekCompleteOption);
  929. logStrHex (" Maximum LAD : ",numLAD-1);
  930. return 0; // error result
  931. }
  932. #endif
  933. /*
  934. * MsgIn2.
  935. */
  936. void MsgIn2(int msg)
  937. {
  938. LOGN("MsgIn2");
  939. SCSI_OUT(vMSG, active) // gpio_write(MSG, high);
  940. SCSI_OUT(vCD , active) // gpio_write(CD, high);
  941. SCSI_OUT(vIO , active) // gpio_write(IO, high);
  942. writeHandshake(msg);
  943. }
  944. /*
  945. * MsgOut2.
  946. */
  947. void MsgOut2()
  948. {
  949. LOGN("MsgOut2");
  950. SCSI_OUT(vMSG, active) // gpio_write(MSG, high);
  951. SCSI_OUT(vCD , active) // gpio_write(CD, high);
  952. SCSI_OUT(vIO ,inactive) // gpio_write(IO, low);
  953. m_msb[m_msc] = readHandshake();
  954. m_msc++;
  955. m_msc %= 256;
  956. }
  957. /*
  958. * Main loop.
  959. */
  960. void loop()
  961. {
  962. //int msg = 0;
  963. m_msg = 0;
  964. // Wait until RST = H, BSY = H, SEL = L
  965. do {} while( SCSI_IN(vBSY) || !SCSI_IN(vSEL) || SCSI_IN(vRST));
  966. // BSY+ SEL-
  967. // If the ID to respond is not driven, wait for the next
  968. //byte db = readIO();
  969. //byte scsiid = db & scsi_id_mask;
  970. byte scsiid = readIO() & scsi_id_mask;
  971. if((scsiid) == 0) {
  972. return;
  973. }
  974. LOGN("Selection");
  975. m_isBusReset = false;
  976. // Set BSY to-when selected
  977. SCSI_BSY_ACTIVE(); // Turn only BSY output ON, ACTIVE
  978. // Ask for a TARGET-ID to respond
  979. #if USE_DB2ID_TABLE
  980. m_id = db2scsiid[scsiid];
  981. //if(m_id==0xff) return;
  982. #else
  983. for(m_id=7;m_id>=0;m_id--)
  984. if(scsiid & (1<<m_id)) break;
  985. //if(m_id<0) return;
  986. #endif
  987. // Wait until SEL becomes inactive
  988. while(isHigh(gpio_read(SEL))) {
  989. if(m_isBusReset) {
  990. goto BusFree;
  991. }
  992. }
  993. SCSI_TARGET_ACTIVE() // (BSY), REQ, MSG, CD, IO output turned on
  994. //
  995. if(isHigh(gpio_read(ATN))) {
  996. bool syncenable = false;
  997. int syncperiod = 50;
  998. int syncoffset = 0;
  999. m_msc = 0;
  1000. memset(m_msb, 0x00, sizeof(m_msb));
  1001. while(isHigh(gpio_read(ATN))) {
  1002. MsgOut2();
  1003. }
  1004. for(int i = 0; i < m_msc; i++) {
  1005. // ABORT
  1006. if (m_msb[i] == 0x06) {
  1007. goto BusFree;
  1008. }
  1009. // BUS DEVICE RESET
  1010. if (m_msb[i] == 0x0C) {
  1011. syncoffset = 0;
  1012. goto BusFree;
  1013. }
  1014. // IDENTIFY
  1015. if (m_msb[i] >= 0x80) {
  1016. }
  1017. // Extended message
  1018. if (m_msb[i] == 0x01) {
  1019. // Check only when synchronous transfer is possible
  1020. if (!syncenable || m_msb[i + 2] != 0x01) {
  1021. MsgIn2(0x07);
  1022. break;
  1023. }
  1024. // Transfer period factor(50 x 4 = Limited to 200ns)
  1025. syncperiod = m_msb[i + 3];
  1026. if (syncperiod > 50) {
  1027. syncoffset = 50;
  1028. }
  1029. // REQ/ACK offset(Limited to 16)
  1030. syncoffset = m_msb[i + 4];
  1031. if (syncoffset > 16) {
  1032. syncoffset = 16;
  1033. }
  1034. // STDR response message generation
  1035. MsgIn2(0x01);
  1036. MsgIn2(0x03);
  1037. MsgIn2(0x01);
  1038. MsgIn2(syncperiod);
  1039. MsgIn2(syncoffset);
  1040. break;
  1041. }
  1042. }
  1043. }
  1044. LOG("Command:");
  1045. SCSI_OUT(vMSG,inactive) // gpio_write(MSG, low);
  1046. SCSI_OUT(vCD , active) // gpio_write(CD, high);
  1047. SCSI_OUT(vIO ,inactive) // gpio_write(IO, low);
  1048. int len;
  1049. byte cmd[12];
  1050. cmd[0] = readHandshake(); if(m_isBusReset) goto BusFree;
  1051. LOGHEX(cmd[0]);
  1052. // Command length selection, reception
  1053. static const int cmd_class_len[8]={6,10,10,6,6,12,6,6};
  1054. len = cmd_class_len[cmd[0] >> 5];
  1055. cmd[1] = readHandshake(); LOG(":");LOGHEX(cmd[1]); if(m_isBusReset) goto BusFree;
  1056. cmd[2] = readHandshake(); LOG(":");LOGHEX(cmd[2]); if(m_isBusReset) goto BusFree;
  1057. cmd[3] = readHandshake(); LOG(":");LOGHEX(cmd[3]); if(m_isBusReset) goto BusFree;
  1058. cmd[4] = readHandshake(); LOG(":");LOGHEX(cmd[4]); if(m_isBusReset) goto BusFree;
  1059. cmd[5] = readHandshake(); LOG(":");LOGHEX(cmd[5]); if(m_isBusReset) goto BusFree;
  1060. // Receive the remaining commands
  1061. for(int i = 6; i < len; i++ ) {
  1062. cmd[i] = readHandshake();
  1063. LOG(":");
  1064. LOGHEX(cmd[i]);
  1065. if(m_isBusReset) goto BusFree;
  1066. }
  1067. // LUN confirmation
  1068. m_lun = m_sts>>5;
  1069. m_sts = cmd[1]&0xe0; // Preset LUN in status byte
  1070. // HDD Image selection
  1071. m_img = (HDDIMG *)0; // None
  1072. if( (m_lun <= NUM_SCSILUN) )
  1073. {
  1074. m_img = &(img[m_id][m_lun]); // There is an image
  1075. if(!(m_img->m_file.isOpen()))
  1076. m_img = (HDDIMG *)0; // Image absent
  1077. }
  1078. // if(!m_img) m_sts |= 0x02; // Missing image file for LUN
  1079. //LOGHEX(((uint32_t)m_img));
  1080. LOG(":ID ");
  1081. LOG(m_id);
  1082. LOG(":LUN ");
  1083. LOG(m_lun);
  1084. LOGN("");
  1085. switch(cmd[0]) {
  1086. case 0x00:
  1087. LOGN("[Test Unit]");
  1088. break;
  1089. case 0x01:
  1090. LOGN("[Rezero Unit]");
  1091. break;
  1092. case 0x03:
  1093. LOGN("[RequestSense]");
  1094. onRequestSenseCommand(cmd[4]);
  1095. break;
  1096. case 0x04:
  1097. LOGN("[FormatUnit]");
  1098. break;
  1099. case 0x06:
  1100. LOGN("[FormatUnit]");
  1101. break;
  1102. case 0x07:
  1103. LOGN("[ReassignBlocks]");
  1104. break;
  1105. case 0x08:
  1106. LOGN("[Read6]");
  1107. m_sts |= onReadCommand((((uint32_t)cmd[1] & 0x1F) << 16) | ((uint32_t)cmd[2] << 8) | cmd[3], (cmd[4] == 0) ? 0x100 : cmd[4]);
  1108. break;
  1109. case 0x0A:
  1110. LOGN("[Write6]");
  1111. m_sts |= onWriteCommand((((uint32_t)cmd[1] & 0x1F) << 16) | ((uint32_t)cmd[2] << 8) | cmd[3], (cmd[4] == 0) ? 0x100 : cmd[4]);
  1112. break;
  1113. case 0x0B:
  1114. LOGN("[Seek6]");
  1115. break;
  1116. case 0x12:
  1117. LOGN("[Inquiry]");
  1118. m_sts |= onInquiryCommand(cmd[4]);
  1119. break;
  1120. case 0x1A:
  1121. LOGN("[ModeSense6]");
  1122. m_sts |= onModeSenseCommand(cmd[1]&0x80, cmd[2], cmd[4]);
  1123. break;
  1124. case 0x1B:
  1125. LOGN("[StartStopUnit]");
  1126. break;
  1127. case 0x1E:
  1128. LOGN("[PreAllowMed.Removal]");
  1129. break;
  1130. case 0x25:
  1131. LOGN("[ReadCapacity]");
  1132. m_sts |= onReadCapacityCommand(cmd[8]);
  1133. break;
  1134. case 0x28:
  1135. LOGN("[Read10]");
  1136. m_sts |= onReadCommand(((uint32_t)cmd[2] << 24) | ((uint32_t)cmd[3] << 16) | ((uint32_t)cmd[4] << 8) | cmd[5], ((uint32_t)cmd[7] << 8) | cmd[8]);
  1137. break;
  1138. case 0x2A:
  1139. LOGN("[Write10]");
  1140. m_sts |= onWriteCommand(((uint32_t)cmd[2] << 24) | ((uint32_t)cmd[3] << 16) | ((uint32_t)cmd[4] << 8) | cmd[5], ((uint32_t)cmd[7] << 8) | cmd[8]);
  1141. break;
  1142. case 0x2B:
  1143. LOGN("[Seek10]");
  1144. break;
  1145. case 0x5A:
  1146. LOGN("[ModeSense10]");
  1147. onModeSenseCommand(cmd[1] & 0x80, cmd[2], ((uint32_t)cmd[7] << 8) | cmd[8]);
  1148. break;
  1149. #if SCSI_SELECT == 1
  1150. case 0xc2:
  1151. LOGN("[DTC510B setDriveParameter]");
  1152. m_sts |= dtc510b_setDriveparameter();
  1153. break;
  1154. #endif
  1155. default:
  1156. LOGN("[*Unknown]");
  1157. m_sts |= 0x02;
  1158. m_senseKey = 5;
  1159. break;
  1160. }
  1161. if(m_isBusReset) {
  1162. goto BusFree;
  1163. }
  1164. LOGN("Sts");
  1165. SCSI_OUT(vMSG,inactive) // gpio_write(MSG, low);
  1166. SCSI_OUT(vCD , active) // gpio_write(CD, high);
  1167. SCSI_OUT(vIO , active) // gpio_write(IO, high);
  1168. writeHandshake(m_sts);
  1169. if(m_isBusReset) {
  1170. goto BusFree;
  1171. }
  1172. LOGN("MsgIn");
  1173. SCSI_OUT(vMSG, active) // gpio_write(MSG, high);
  1174. SCSI_OUT(vCD , active) // gpio_write(CD, high);
  1175. SCSI_OUT(vIO , active) // gpio_write(IO, high);
  1176. writeHandshake(m_msg);
  1177. BusFree:
  1178. LOGN("BusFree");
  1179. m_isBusReset = false;
  1180. //SCSI_OUT(vREQ,inactive) // gpio_write(REQ, low);
  1181. //SCSI_OUT(vMSG,inactive) // gpio_write(MSG, low);
  1182. //SCSI_OUT(vCD ,inactive) // gpio_write(CD, low);
  1183. //SCSI_OUT(vIO ,inactive) // gpio_write(IO, low);
  1184. //SCSI_OUT(vBSY,inactive)
  1185. SCSI_TARGET_INACTIVE() // Turn off BSY, REQ, MSG, CD, IO output
  1186. }