Drivers for the MNT ZZ9000 graphics and ARM coprocessor card for classic Amigas.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

633 lines
16 KiB

  1. /*
  2. * Amiga ZZ9000 USB Storage Driver (ZZ9000USBStorage.device)
  3. * Copyright (C) 2016-2020, Lukas F. Hartmann <lukas@mntre.com>
  4. * Based on code Copyright (C) 2016, Jason S. McMullan <jason.mcmullan@gmail.com>
  5. * All rights reserved.
  6. *
  7. * Licensed under the MIT License:
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining
  10. * a copy of this software and associated documentation files (the "Software"),
  11. * to deal in the Software without restriction, including without limitation
  12. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13. * and/or sell copies of the Software, and to permit persons to whom the
  14. * Software is furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included
  17. * in all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  24. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  25. * DEALINGS IN THE SOFTWARE.
  26. */
  27. #include <exec/resident.h>
  28. #include <exec/errors.h>
  29. #include <exec/memory.h>
  30. #include <exec/lists.h>
  31. #include <exec/alerts.h>
  32. #include <exec/tasks.h>
  33. #include <exec/io.h>
  34. #include <exec/execbase.h>
  35. #include <libraries/expansion.h>
  36. #include <devices/trackdisk.h>
  37. #include <devices/timer.h>
  38. #include <devices/scsidisk.h>
  39. #include <dos/filehandler.h>
  40. #include <proto/exec.h>
  41. #include <proto/disk.h>
  42. #include <proto/expansion.h>
  43. struct ExecBase* SysBase;
  44. const char DevName[]="ZZ9000USBStorage.device";
  45. const char DevIdString[]="ZZ9000USBStorage 1.0 (01 Dec 2019)";
  46. const UWORD DevVersion=1;
  47. const UWORD DevRevision=7;
  48. #include "stabs.h"
  49. #include "mntsd_cmd.h"
  50. struct SDBase* SDBase;
  51. #define debug(x,args...) while(0){};
  52. #define kprintf(x,args...) while(0){};
  53. //#define bug(x,args...) kprintf(x ,##args);
  54. //#define debug(x,args...) bug("%s:%ld " x "\n", __func__, (unsigned long)__LINE__ ,##args)
  55. struct WBStartup *_WBenchMsg;
  56. void _cleanup() {}
  57. void SD_InitUnit(struct SDBase* SDBase, int id, uint8* registers);
  58. LONG SD_PerformIO(struct SDUnit* sdu, struct IORequest *io);
  59. LONG SD_PerformSCSI(struct SDUnit* sdu, struct IORequest *io);
  60. // struct Device is just a Library http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_3._guide/node05FB.html#line23 (dev->dd_Library)
  61. extern void* DOSBase[2]; // part of libnix startup foo
  62. int __UserDevInit(struct Device* dev)
  63. {
  64. struct Library* ExpansionBase;
  65. struct ConfigDev* cd = NULL;
  66. uint8* registers = NULL;
  67. uint32 i;
  68. SysBase = *(struct ExecBase **)4L;
  69. if ((ExpansionBase = (struct Library*)OpenLibrary("expansion.library",0L))==NULL) {
  70. return 0;
  71. }
  72. if (cd = (struct ConfigDev*)FindConfigDev(cd,0x6d6e,0x3)) {
  73. debug("ZZ9000USBStorage.device found ZZ9000 (Zorro II).\n");
  74. registers = ((uint8*)cd->cd_BoardAddr)+0xd0;
  75. CloseLibrary(ExpansionBase);
  76. } else {
  77. if (cd = (struct ConfigDev*)FindConfigDev(cd,0x6d6e,0x4)) {
  78. debug("ZZ9000USBStorage.device found ZZ9000 (Zorro III).\n");
  79. registers = ((uint8*)cd->cd_BoardAddr)+0xd0;
  80. CloseLibrary(ExpansionBase);
  81. } else {
  82. debug("ZZ9000USBStorage.device didn't find ZZ9000!\n");
  83. CloseLibrary(ExpansionBase);
  84. return 0;
  85. }
  86. }
  87. SDBase = AllocMem(sizeof(struct SDBase), MEMF_PUBLIC|MEMF_CLEAR);
  88. if (!SDBase) return 0;
  89. for (i = 0; i < SD_UNITS; i++) SD_InitUnit(SDBase, i, registers);
  90. return 1;
  91. }
  92. int main(void) {
  93. return 0;
  94. }
  95. int __UserDevCleanup(void)
  96. {
  97. // FIXME dealloc SDBase
  98. return 0;
  99. }
  100. int __UserDevOpen(struct IOExtTD *iotd, ULONG unitnum, ULONG flags)
  101. {
  102. struct Node* node = (struct Node*)iotd;
  103. int io_err = IOERR_OPENFAIL;
  104. if (iotd && unitnum==0) {
  105. io_err = 0;
  106. iotd->iotd_Req.io_Unit = (struct Unit*)&SDBase->sd_Unit[unitnum];
  107. iotd->iotd_Req.io_Unit->unit_flags = UNITF_ACTIVE;
  108. iotd->iotd_Req.io_Unit->unit_OpenCnt = 1;
  109. }
  110. iotd->iotd_Req.io_Error = io_err;
  111. return io_err;
  112. }
  113. int __UserDevClose(struct IOExtTD *iotd)
  114. {
  115. return 0;
  116. }
  117. ADDTABL_1(__BeginIO,a1);
  118. void __BeginIO(struct IORequest *io) {
  119. struct SDUnit* sdu;
  120. struct Node* node = (struct Node*)io;
  121. if (!SDBase) return;
  122. sdu = &SDBase->sd_Unit[0]; // (struct SDUnit *)io->io_Unit;
  123. if (!sdu) return;
  124. if (!io) return;
  125. //debug("io_Command = %ld, io_Flags = 0x%lx quick = %lx", io->io_Command, io->io_Flags, (io->io_Flags & IOF_QUICK));
  126. io->io_Error = SD_PerformIO(sdu, io);
  127. if (!(io->io_Flags & IOF_QUICK)) {
  128. // ReplyMsg does this: io->io_Message.mn_Node.ln_Type = NT_REPLYMSG;
  129. ReplyMsg(&io->io_Message);
  130. }
  131. }
  132. ADDTABL_1(__AbortIO,a1);
  133. void __AbortIO(struct IORequest* io) {
  134. if (!io) return;
  135. io->io_Error = IOERR_ABORTED;
  136. }
  137. void SD_InitUnit(struct SDBase* SDBase, int id, uint8* registers)
  138. {
  139. struct SDUnit *sdu = &SDBase->sd_Unit[id];
  140. if (id == 0) {
  141. sdu->sdu_Registers = (void*)registers;
  142. sdu->sdu_Enabled = 1;
  143. sdu->sdu_Present = 1;
  144. sdu->sdu_Valid = 1;
  145. sdu->sdu_ChangeNum++;
  146. sd_reset(sdu->sdu_Registers);
  147. }
  148. }
  149. uint32 SD_ReadWrite(struct SDUnit *sdu, struct IORequest *io, uint32 offset, BOOL is_write)
  150. {
  151. struct IOStdReq *iostd = (struct IOStdReq *)io;
  152. struct IOExtTD *iotd = (struct IOExtTD *)io;
  153. uint8* data;
  154. uint32 len, num_blocks;
  155. uint32 block, max_addr;
  156. uint16 sderr;
  157. if (!sdu || !io) return 0;
  158. data = iotd->iotd_Req.io_Data;
  159. len = iotd->iotd_Req.io_Length;
  160. max_addr = 0xffffffff; //SD_CYL_SECTORS * SD_CYLS * SD_SECTOR_BYTES;
  161. // well... if we had 64 bits this would make sense
  162. if ((offset > max_addr) || (offset+len > max_addr)) {
  163. return IOERR_BADADDRESS;
  164. }
  165. if (data == 0) {
  166. return IOERR_BADADDRESS;
  167. }
  168. if (len < SD_SECTOR_BYTES) {
  169. iostd->io_Actual = 0;
  170. return IOERR_BADLENGTH;
  171. }
  172. block = offset >> SD_SECTOR_SHIFT;
  173. num_blocks = len >> SD_SECTOR_SHIFT;
  174. sderr = 0;
  175. if (is_write) {
  176. uint32 retries = 10;
  177. do {
  178. debug("write %lx %lx retry %lx regs %lx",block,num_blocks,retries,sdu->sdu_Registers);
  179. sderr = sdcmd_write_blocks(sdu->sdu_Registers, data, block, num_blocks);
  180. if (sderr) {
  181. debug("err %x",sderr);
  182. sd_reset(sdu->sdu_Registers);
  183. }
  184. retries--;
  185. } while (sderr && retries>0);
  186. debug("write done");
  187. } else {
  188. debug("read %lx %lx",block,num_blocks);
  189. sderr = sdcmd_read_blocks(sdu->sdu_Registers, data, block, num_blocks);
  190. if (sderr) {
  191. debug("err %x",sderr);
  192. } else {
  193. debug("read done");
  194. }
  195. }
  196. if (sderr) {
  197. iostd->io_Actual = 0;
  198. if (sderr & SDERRF_TIMEOUT)
  199. return TDERR_DiskChanged;
  200. if (sderr & SDERRF_PARAM)
  201. return TDERR_SeekError;
  202. if (sderr & SDERRF_ADDRESS)
  203. return TDERR_SeekError;
  204. if (sderr & (SDERRF_ERASESEQ | SDERRF_ERASERES))
  205. return TDERR_BadSecPreamble;
  206. if (sderr & SDERRF_CRC)
  207. return TDERR_BadSecSum;
  208. if (sderr & SDERRF_ILLEGAL)
  209. return TDERR_TooFewSecs;
  210. if (sderr & SDERRF_IDLE)
  211. return TDERR_PostReset;
  212. return TDERR_SeekError;
  213. } else {
  214. iostd->io_Actual = len;
  215. }
  216. return 0;
  217. }
  218. LONG SD_PerformIO(struct SDUnit *sdu, struct IORequest *io)
  219. {
  220. struct IOStdReq *iostd = (struct IOStdReq *)io;
  221. struct IOExtTD *iotd = (struct IOExtTD *)io;
  222. APTR data;
  223. uint32 len;
  224. uint32 offset;
  225. //struct DriveGeometry *geom;
  226. uint32 err = IOERR_NOCMD;
  227. int i;
  228. if (!io) return err;
  229. if (!sdu) return err;
  230. if (!sdu->sdu_Enabled) {
  231. return IOERR_OPENFAIL;
  232. }
  233. data = iotd->iotd_Req.io_Data;
  234. len = iotd->iotd_Req.io_Length;
  235. if (io->io_Error == IOERR_ABORTED) {
  236. return io->io_Error;
  237. }
  238. //debug("cmd: %s",cmd_name(io->io_Command));
  239. //debug("IO %lx Start, io_Flags = %ld, io_Command = %ld (%s)", io, io->io_Flags, io->io_Command, cmd_name(io->io_Command));
  240. switch (io->io_Command) {
  241. case CMD_CLEAR:
  242. /* Invalidate read buffer */
  243. iostd->io_Actual = 0;
  244. err = 0;
  245. break;
  246. case CMD_UPDATE:
  247. /* Flush write buffer */
  248. iostd->io_Actual = 0;
  249. err = 0;
  250. break;
  251. case TD_PROTSTATUS:
  252. iostd->io_Actual = 0;
  253. err = 0;
  254. break;
  255. case TD_CHANGENUM:
  256. iostd->io_Actual = sdu->sdu_ChangeNum;
  257. err = 0;
  258. break;
  259. case TD_REMOVE:
  260. iostd->io_Actual = 0;
  261. err = 0;
  262. break;
  263. case TD_CHANGESTATE:
  264. iostd->io_Actual = 0;
  265. err = 0;
  266. break;
  267. case TD_GETDRIVETYPE:
  268. iostd->io_Actual = DG_DIRECT_ACCESS;
  269. err = 0;
  270. break;
  271. case TD_MOTOR:
  272. iostd->io_Actual = sdu->sdu_Motor;
  273. sdu->sdu_Motor = iostd->io_Length ? 1 : 0;
  274. err = 0;
  275. break;
  276. case TD_FORMAT:
  277. offset = iotd->iotd_Req.io_Offset;
  278. err = SD_ReadWrite(sdu, io, offset, 1);
  279. break;
  280. case CMD_WRITE:
  281. offset = iotd->iotd_Req.io_Offset;
  282. err = SD_ReadWrite(sdu, io, offset, 1);
  283. break;
  284. case CMD_READ:
  285. offset = iotd->iotd_Req.io_Offset;
  286. err = SD_ReadWrite(sdu, io, offset, 0);
  287. break;
  288. case HD_SCSICMD:
  289. err = SD_PerformSCSI(sdu, io);
  290. break;
  291. default:
  292. //kprintf("Unknown IO command: %ld\n", io->io_Command);
  293. err = IOERR_NOCMD;
  294. break;
  295. }
  296. return err;
  297. }
  298. LONG SD_PerformSCSI(struct SDUnit *sdu, struct IORequest *io)
  299. {
  300. struct IOStdReq *iostd = (struct IOStdReq *)io;
  301. struct SCSICmd *scsi = iostd->io_Data;
  302. uint8* registers = sdu->sdu_Registers;
  303. uint8* data = (uint8*)scsi->scsi_Data;
  304. uint32 i, block, blocks, maxblocks;
  305. long err;
  306. uint8 r1;
  307. /*debug("SCSI len=%ld, cmd = %02lx %02lx %02lx ... (%ld)",
  308. iostd->io_Length, scsi->scsi_Command[0],
  309. scsi->scsi_Command[1], scsi->scsi_Command[2],
  310. scsi->scsi_CmdLength);*/
  311. maxblocks = SD_CYL_SECTORS * SD_CYLS;
  312. if (scsi->scsi_CmdLength < 6) {
  313. //debug("SCSICMD BADLENGTH2");
  314. return IOERR_BADLENGTH;
  315. }
  316. if (scsi->scsi_Command == NULL) {
  317. //debug("SCSICMD IOERR_BADADDRESS1");
  318. return IOERR_BADADDRESS;
  319. }
  320. scsi->scsi_Actual = 0;
  321. switch (scsi->scsi_Command[0]) {
  322. case 0x00: // TEST_UNIT_READY
  323. err = 0;
  324. break;
  325. case 0x12: // INQUIRY
  326. for (i = 0; i < scsi->scsi_Length; i++) {
  327. uint8 val;
  328. switch (i) {
  329. case 0: // SCSI device type: direct-access device
  330. val = (0 << 5) | 0;
  331. break;
  332. case 1: // RMB = 1
  333. val = (1 << 7);
  334. break;
  335. case 2: // VERSION = 0
  336. val = 0;
  337. break;
  338. case 3: // NORMACA=0, HISUP = 0, RESPONSE_DATA_FORMAT = 2
  339. val = (0 << 5) | (0 << 4) | 2;
  340. break;
  341. case 4: // ADDITIONAL_LENGTH = 44 - 4
  342. val = 44 - 4;
  343. break;
  344. default:
  345. if (i >= 8 && i < 16)
  346. val = "MNT "[i - 8];
  347. else if (i >= 16 && i < 32)
  348. val = "ZZ9000 USB Disk "[i - 16];
  349. else if (i >= 32 && i < 36)
  350. val = "1.5 "[i-32];
  351. else if (i >= 36 && i < 44) {
  352. val = '1';
  353. } else
  354. val = 0;
  355. break;
  356. }
  357. data[i] = val;
  358. }
  359. scsi->scsi_Actual = i;
  360. err = 0;
  361. break;
  362. case 0x08: // READ (6)
  363. block = scsi->scsi_Command[1] & 0x1f;
  364. block = (block << 8) | scsi->scsi_Command[2];
  365. block = (block << 8) | scsi->scsi_Command[3];
  366. blocks = scsi->scsi_Command[4];
  367. debug("scsi_read %lx %lx\n",block,blocks);
  368. if (block + blocks > maxblocks) {
  369. err = IOERR_BADADDRESS;
  370. break;
  371. }
  372. if (scsi->scsi_Length < (blocks << SD_SECTOR_SHIFT)) {
  373. err = IOERR_BADLENGTH;
  374. break;
  375. }
  376. if (data == NULL) {
  377. err = IOERR_BADADDRESS;
  378. break;
  379. }
  380. r1 = sdcmd_read_blocks(registers, data, block, blocks);
  381. if (r1) {
  382. err = HFERR_BadStatus;
  383. break;
  384. }
  385. scsi->scsi_Actual = scsi->scsi_Length;
  386. err = 0;
  387. break;
  388. case 0x0a: // WRITE (6)
  389. block = scsi->scsi_Command[1] & 0x1f;
  390. block = (block << 8) | scsi->scsi_Command[2];
  391. block = (block << 8) | scsi->scsi_Command[3];
  392. blocks = scsi->scsi_Command[4];
  393. if (block + blocks > maxblocks) {
  394. err = IOERR_BADADDRESS;
  395. break;
  396. }
  397. if (scsi->scsi_Length < (blocks << SD_SECTOR_SHIFT)) {
  398. err = IOERR_BADLENGTH;
  399. break;
  400. }
  401. if (data == NULL) {
  402. err = IOERR_BADADDRESS;
  403. break;
  404. }
  405. debug("scsi_write %lx %lx\n",block,blocks);
  406. r1 = sdcmd_write_blocks(registers, data, block, blocks);
  407. if (r1) {
  408. err = HFERR_BadStatus;
  409. break;
  410. }
  411. scsi->scsi_Actual = scsi->scsi_Length;
  412. err = 0;
  413. break;
  414. case 0x25: // READ CAPACITY (10)
  415. if (scsi->scsi_CmdLength < 10) {
  416. err = HFERR_BadStatus;
  417. break;
  418. }
  419. block = *((uint32*)&scsi->scsi_Command[2]);
  420. if ((scsi->scsi_Command[8] & 1) || block != 0) {
  421. // PMI Not supported
  422. err = HFERR_BadStatus;
  423. break;
  424. }
  425. if (scsi->scsi_Length < 8) {
  426. err = IOERR_BADLENGTH;
  427. break;
  428. }
  429. ((uint32*)data)[0] = sdcmd_capacity(registers)-1;
  430. ((uint32*)data)[1] = SD_SECTOR_BYTES;
  431. scsi->scsi_Actual = 8;
  432. err = 0;
  433. break;
  434. case 0x1a: // MODE SENSE (6)
  435. data[0] = 3 + 8 + 0x16;
  436. data[1] = 0; // MEDIUM TYPE
  437. data[2] = 0;
  438. data[3] = 8;
  439. if (maxblocks > (1 << 24))
  440. blocks = 0xffffff;
  441. else
  442. blocks = maxblocks;
  443. data[4] = (blocks >> 16) & 0xff;
  444. data[5] = (blocks >> 8) & 0xff;
  445. data[6] = (blocks >> 0) & 0xff;
  446. data[7] = 0;
  447. data[8] = 0;
  448. data[9] = 0;
  449. data[10] = (SD_SECTOR_BYTES >> 8) & 0xff;
  450. data[11] = (SD_SECTOR_BYTES >> 0) & 0xff;
  451. switch (((UWORD)scsi->scsi_Command[2] << 8) | scsi->scsi_Command[3]) {
  452. case 0x0300: // Format Device Mode
  453. for (i = 0; i < scsi->scsi_Length - 12; i++) {
  454. UBYTE val;
  455. switch (i) {
  456. case 0: // PAGE CODE
  457. val = 0x03;
  458. break;
  459. case 1: // PAGE LENGTH
  460. val = 0x16;
  461. break;
  462. case 2: // TRACKS PER ZONE 15..8
  463. val = (SD_HEADS >> 8) & 0xff;
  464. break;
  465. case 3: // TRACKS PER ZONE 7..0
  466. val = (SD_HEADS >> 0) & 0xff;
  467. break;
  468. case 10: // SECTORS PER TRACK 15..8
  469. val = (SD_TRACK_SECTORS >> 8) & 0xff;
  470. break;
  471. case 11: // SECTORS PER TRACK 7..0
  472. val = (SD_TRACK_SECTORS >> 0) & 0xff;
  473. break;
  474. case 12: // DATA BYTES PER PHYSICAL SECTOR 15..8
  475. val = (SD_SECTOR_BYTES >> 8) & 0xff;
  476. break;
  477. case 13: // DATA BYTES PER PHYSICAL SECTOR 7..0
  478. val = (SD_SECTOR_BYTES >> 0) & 0xff;
  479. break;
  480. case 20: // HSEC = 1, RMB = 1
  481. val = (1 << 6) | (1 << 5);
  482. break;
  483. default:
  484. val = 0;
  485. break;
  486. }
  487. data[12 + i] = val;
  488. }
  489. scsi->scsi_Actual = data[0] + 1;
  490. err = 0;
  491. break;
  492. case 0x0400: // Rigid Drive Geometry
  493. for (i = 0; i < scsi->scsi_Length - 12; i++) {
  494. UBYTE val;
  495. switch (i) {
  496. case 0: // PAGE CODE
  497. val = 0x04;
  498. break;
  499. case 1: // PAGE LENGTH
  500. val = 0x16;
  501. break;
  502. case 2: // CYLINDERS 23..16
  503. val = (SD_CYLS >> 16) & 0xff;
  504. break;
  505. case 3: // CYLINDERS 15..8
  506. val = (SD_CYLS >> 8) & 0xff;
  507. break;
  508. case 4: // CYLINDERS 7..0
  509. val = (SD_CYLS >> 0) & 0xff;
  510. break;
  511. case 5: // HEADS
  512. val = SD_HEADS;
  513. break;
  514. default:
  515. val = 0;
  516. break;
  517. }
  518. data[12 + i] = val;
  519. }
  520. scsi->scsi_Actual = data[0] + 1;
  521. err = 0;
  522. break;
  523. default:
  524. err = HFERR_BadStatus;
  525. break;
  526. }
  527. break;
  528. default:
  529. err = IOERR_NOCMD;
  530. break;
  531. }
  532. if (err == 0) {
  533. iostd->io_Actual = sizeof(*scsi);
  534. }
  535. else {
  536. iostd->io_Actual = 0;
  537. }
  538. return err;
  539. }
  540. ADDTABL_END();