abcdisk.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  1. /*
  2. * abcdisk.c
  3. *
  4. * Emulate an ABC80/800 disk controller
  5. */
  6. #include <string.h>
  7. #include <stdio.h>
  8. #include "common.h"
  9. #include "config.h"
  10. #include "io.h"
  11. #include "abcio.h"
  12. #include "console.h"
  13. #include "sdcard.h"
  14. #include "ff.h"
  15. /* Option flags, mostly for debugging */
  16. #define NOTTHERE 0
  17. #define READONLY 0
  18. #define INTERLEAVE 0
  19. #define FORMAT_SUPPORT 0
  20. enum drive_flags {
  21. DF_MOUNTED = 1, /* Host file open, drive exported */
  22. DF_READONLY = 2, /* Drive is readonly */
  23. DF_DISABLED = 4, /* Drive is disabled */
  24. DF_DIRTY = 8 /* Disk has been written */
  25. };
  26. enum pending {
  27. PEND_IO = 1, /* I/O transfer complete */
  28. PEND_STARTCMD = 2, /* C1# = go to command state */
  29. PEND_RESET = 4 /* C3# or RST# = local/global reset */
  30. };
  31. /*
  32. * Status bits in INP(1); bits 5 & 2 are unknown, bit 4 is apparently
  33. * always 0 on at least card 66 81046-02 (55 21046-x1)...
  34. * "fast DMA controller".
  35. */
  36. enum abc_status {
  37. AS_CMD = 0x80, /* Start of command */
  38. AS_WRITE = 0x40, /* Data direction OUT(0) (to controller) */
  39. AS_ERROR = 0x08, /* INP(0) contains error info */
  40. AS_READING = 0x04, /* Waiting for sector load */
  41. AS_READY = 0x01 /* Ready for input */
  42. };
  43. /* Number of fragments (extents) we can memoize */
  44. #define MAX_FAST_FRAGMENTS 16
  45. #define CLTBL_SIZE ((MAX_FAST_FRAGMENTS+1)*2)
  46. /* Per-drive state */
  47. struct drive_state {
  48. FIL file; /* Host file */
  49. char name[4]; /* Drive name */
  50. uint16_t sectors; /* Total size in 256-byte sectors */
  51. #if INTERLEAVE
  52. uint8_t ilmsk, ilfac; /* Software interleaving parameters */
  53. #endif
  54. enum drive_flags flags;
  55. enum drive_flags force; /* Option to force flags */
  56. DWORD cltbl[CLTBL_SIZE]; /* Extent map */
  57. };
  58. /* Fixed parameters for each controller */
  59. struct ctl_params {
  60. enum sysvar_enum enable; /* Enable configuration variable */
  61. enum sysvar_enum devsel; /* Device select code variable */
  62. uint8_t clustshift; /* log2(clustersize/256) */
  63. uint16_t maxsectors; /* Maximum sectors for this controller */
  64. uint8_t c, h, s; /* Disk geometry */
  65. bool newaddr; /* "New addressing" */
  66. const char name[4]; /* Name of controller (disk type) */
  67. #if INTERLEAVE
  68. uint8_t ilmsk, ilfac; /* Software interleaving parea */
  69. #endif
  70. #if FORMAT_SUPPORT
  71. bool fmtdata_i_buf; /* Use user-provided formatting data */
  72. #endif
  73. } __attribute__((aligned(4)));
  74. /* Per-controller state */
  75. struct ctl_state {
  76. struct abc_dev iodev;
  77. const struct ctl_params *params;
  78. uint8_t k[4]; /* Command bytes */
  79. uint8_t drives; /* Total drives present */
  80. uint8_t error; /* Error status */
  81. bool initialized; /* Controller initialized */
  82. volatile enum pending pending; /* Need to do I/O */
  83. struct drive_state drv[8]; /* Per-drive state */
  84. uint8_t buf[4][256]; /* 4 host buffers @ 256 bytes */
  85. };
  86. /*
  87. * Error codes for INP(0), derived from FD1791 status codes
  88. *
  89. * DOSGEN depends on OUT_OF_RANGE having this value... and different
  90. * DOSGEN expect different values. If this value is wrong, DOSGEN will
  91. * spin forever on "testing sector..."
  92. */
  93. #define OUT_OF_RANGE 0x21 /* Status code for an invalid sector */
  94. #define DISK_NOT_READY 0x80
  95. #define WRITE_PROTECT 0x40
  96. #define WRITE_FAULT 0x20
  97. #define CRC_ERROR 0x08
  98. enum controller_types {
  99. MOx,
  100. MFx,
  101. SFx,
  102. HDx,
  103. XDx,
  104. CONTROLLER_TYPES
  105. };
  106. #if INTERLEAVE
  107. # define IL(mask, fac) .ilmsk = (mask), .ilfac = (fac),
  108. #else
  109. # define IL(mask, fac)
  110. #endif
  111. static const struct ctl_params parameters[CONTROLLER_TYPES] = {
  112. /*
  113. * MOx: covers all of these formats:
  114. * SSSD = 40×8×1 (80K, FD2/DD80),
  115. * SSDD = 40×16×1 (160K, FD2D/DD82/ABC830) and
  116. * DSDD = 40×16×2 (320K, FD4D/DD84/DD52)
  117. */
  118. [MOx] = {
  119. .enable = config_abc_io_mo_enable,
  120. .devsel = config_abc_io_mo_devsel,
  121. .clustshift = 0,
  122. .maxsectors = 40 * 2 * 16,
  123. .c = 40, .h = 2, .s = 16,
  124. .name = "mo",
  125. #if FORMAT_SUPPORT
  126. .fmtdata_in_buf = true,
  127. #endif
  128. IL(15, 7)
  129. },
  130. /* MFx: DSQD = 80×16x2 (640K, ABC832/834) */
  131. [MFx] = {
  132. .enable = config_abc_io_mf_enable,
  133. .devsel = config_abc_io_mf_devsel,
  134. .clustshift = 2,
  135. .maxsectors = 80 * 2 * 16,
  136. .c = 80, .h = 2, .s = 16,
  137. .name = "mf"
  138. },
  139. /* SFx: 8" floppy (DD88, ABC838) */
  140. [SFx] = {
  141. .enable = config_abc_io_sf_enable,
  142. .devsel = config_abc_io_sf_devsel,
  143. .clustshift = 2,
  144. .maxsectors = (77 * 2 - 1) * 26, /* Track 0, side 0 not used */
  145. .c = 77, .h = 2, .s = 26,
  146. .name = "sf"
  147. },
  148. [HDx] = {
  149. .enable = config_abc_io_hd_enable,
  150. .devsel = config_abc_io_hd_devsel,
  151. .clustshift = 5,
  152. .newaddr = true, /* Actually irrelevant for clustshift = 5 */
  153. .maxsectors = (239 * 8 - 1) * 32, /* Maximum supported by UFD-DOS */
  154. .c = 238, .h = 16, .s = 64,
  155. .name = "hd"
  156. },
  157. /* Second harddisk */
  158. [XDx] = {
  159. .enable = config_abc_io_xd_enable,
  160. .devsel = config_abc_io_xd_devsel,
  161. .clustshift = 5,
  162. .newaddr = true, /* Actually irrelevant for clustshift = 5 */
  163. .maxsectors = (239 * 8 - 1) * 32, /* Maximum supported by UFD-DOS */
  164. .c = 238, .h = 16, .s = 64,
  165. .name = "xd"
  166. },
  167. };
  168. static struct ctl_state __dram_bss controllers[CONTROLLER_TYPES];
  169. static inline bool mounted(const struct drive_state *drv)
  170. {
  171. return !!(drv->flags & DF_MOUNTED);
  172. }
  173. static inline struct drive_state *cur_drv_mutable(struct ctl_state *state)
  174. {
  175. return &state->drv[state->k[1] & 7];
  176. }
  177. static inline const struct drive_state *cur_drv(const struct ctl_state *state)
  178. {
  179. return &state->drv[state->k[1] & 7];
  180. }
  181. static inline unsigned int cur_sector(const struct ctl_state *state)
  182. {
  183. uint8_t k2 = state->k[2], k3 = state->k[3];
  184. if (state->params->newaddr)
  185. return (k2 << 8) + k3;
  186. else
  187. return (((k2 << 3) + (k3 >> 5)) << state->params->clustshift)
  188. + (k3 & 31);
  189. }
  190. /* Get physical sector number, after interleaving */
  191. static inline unsigned int
  192. virt2phys(const struct drive_state *drv, unsigned int sector)
  193. {
  194. #if INTERLEAVE
  195. unsigned int ilmsk = drv->ilmsk;
  196. unsigned int ilfac = drv->ilfac;
  197. sector = (sector & ~ilmsk) | ((sector * ilfac) & ilmsk);
  198. #endif
  199. return sector;
  200. }
  201. static inline unsigned int phys_sector(const struct ctl_state *state)
  202. {
  203. return virt2phys(cur_drv(state), cur_sector(state));
  204. }
  205. static inline unsigned int file_pos(const struct ctl_state *state)
  206. {
  207. return phys_sector(state) << 8;
  208. }
  209. static inline bool file_pos_valid(const struct ctl_state *state)
  210. {
  211. return phys_sector(state) < cur_drv(state)->sectors;
  212. }
  213. static inline bool cur_sector_valid(const struct ctl_state *state)
  214. {
  215. uint8_t k3 = state->k[3];
  216. if (!state->params->newaddr && ((k3 & 31) >> state->params->clustshift))
  217. return false;
  218. return phys_sector(state) < state->params->maxsectors;
  219. }
  220. static inline uint8_t *cur_buf(struct ctl_state *state)
  221. {
  222. return state->buf[state->k[1] >> 6];
  223. }
  224. static void disk_start_command(struct ctl_state *state)
  225. {
  226. #if 0
  227. con_printf("%-2s: start command\n", state->params->name);
  228. #endif
  229. memset(&state->k, 0xee, sizeof state->k);
  230. state->iodev.callback_mask |= 1 << 0;
  231. abc_setup_out_queue(&state->iodev, state->k, 4,
  232. AS_CMD|AS_READY|AS_WRITE|
  233. (state->error ? AS_ERROR : 0));
  234. }
  235. static void sync_drives(struct ctl_state *state)
  236. {
  237. for (int i = 0; i < 8; i++) {
  238. struct drive_state *drv = &state->drv[i];
  239. if (drv->flags & DF_DIRTY) {
  240. f_sync(&state->drv[i].file);
  241. drv->flags &= ~DF_DIRTY;
  242. }
  243. }
  244. }
  245. static void disk_set_error(struct ctl_state *state, unsigned int error)
  246. {
  247. abc_set_inp_default(&state->iodev, state->error = error);
  248. state->k[0] = 0; /* Abort remaining command sequence */
  249. }
  250. static void disk_reset_state(struct ctl_state *state)
  251. {
  252. abc_set_inp_status(&state->iodev, 0);
  253. disk_set_error(state, 0);
  254. disk_start_command(state);
  255. }
  256. static struct drive_state *
  257. name_to_drive(const char *drive)
  258. {
  259. unsigned int ndrive;
  260. /* All drive names are three letters long */
  261. if (strlen(drive) != 3)
  262. return NULL;
  263. ndrive = drive[2] - '0';
  264. if (ndrive > 7)
  265. return NULL;
  266. if (!memcmp("dr", drive, 2)) {
  267. /* DRx alias for MOx (matches "old DOS") */
  268. return &controllers[MOx].drv[ndrive];
  269. }
  270. for (int i = 0; i < CONTROLLER_TYPES; i++) {
  271. struct ctl_state * const state = &controllers[i];
  272. if (!memcmp(state->params->name, drive, 2))
  273. return &state->drv[ndrive];
  274. }
  275. return NULL; /* No such disk */
  276. }
  277. bool valid_drive_name(const char *drive)
  278. {
  279. return name_to_drive(drive) != NULL;
  280. }
  281. static int mount_drive(struct drive_state *drv, struct ctl_state *state,
  282. const char *filename)
  283. {
  284. FRESULT rv;
  285. if (mounted(drv)) {
  286. if (!(sdc.fsstatus & STA_NOINIT))
  287. f_close(&drv->file);
  288. drv->flags &= ~DF_MOUNTED;
  289. state->drives--;
  290. }
  291. if (drv->force & DF_DISABLED)
  292. return -1;
  293. drv->flags = drv->force & ~DF_MOUNTED;
  294. if (!filename) {
  295. return 0; /* Explicit unmount */
  296. } else {
  297. while (1) {
  298. BYTE mode = FA_OPEN_EXISTING | FA_READ;
  299. if (!(drv->flags & DF_READONLY))
  300. mode |= FA_WRITE;
  301. rv = f_open(&drv->file, filename, mode);
  302. if (rv == FR_WRITE_PROTECTED && (mode & FA_WRITE)) {
  303. drv->flags |= DF_READONLY;
  304. continue;
  305. }
  306. drv->flags |= (rv == FR_OK) ? DF_MOUNTED : DF_DISABLED;
  307. break;
  308. }
  309. if (!(drv->flags & DF_MOUNTED))
  310. return -1;
  311. }
  312. con_printf("abcdisk: %-3s = %s\n", drv->name, filename);
  313. /* Try to memoize extents for fast seek */
  314. drv->cltbl[0] = CLTBL_SIZE;
  315. drv->file.cltbl = drv->cltbl;
  316. rv = f_lseek(&drv->file, CREATE_LINKMAP);
  317. if (rv != FR_OK) {
  318. con_printf("abcdisk: %-3s ! file too fragmented, will be slow\n",
  319. drv->name);
  320. }
  321. /*
  322. * Smaller than the standard disk size? Treat the sectors
  323. * beyond the end as bad.
  324. */
  325. unsigned int filesec = f_size(&drv->file) >> 8;
  326. drv->sectors = min(filesec, state->params->maxsectors);
  327. /* Interleaving parameters */
  328. #if INTERLEAVE
  329. drv->ilfac = state->params->ilfac;
  330. drv->ilmsk = state->params->ilmsk;
  331. #endif
  332. state->drives++;
  333. return 0;
  334. }
  335. static void unmount_drives(struct ctl_state *state)
  336. {
  337. int i;
  338. for (int i = 0; i < 8; i++) {
  339. struct drive_state *drv = &state->drv[i];
  340. if (drv->flags & DF_MOUNTED)
  341. mount_drive(drv, state, NULL);
  342. }
  343. }
  344. /* RST# = global reset, C3# = local reset, C1# = goto command start */
  345. #define IDLE_CALLBACK_MASK ((1 << 7)|(1 << 4)|(1 << 2))
  346. static ABC_CALLBACK(abcdisk_callback_out_inp)
  347. {
  348. struct ctl_state * const state = container_of(dev, struct ctl_state, iodev);
  349. dev->callback_mask = IDLE_CALLBACK_MASK;
  350. __abc_set_inp_status(dev, 0);
  351. state->error = 0;
  352. state->pending |= PEND_IO;
  353. }
  354. static ABC_CALLBACK(abcdisk_callback_restart)
  355. {
  356. struct ctl_state * const state = container_of(dev, struct ctl_state, iodev);
  357. state->pending |= PEND_STARTCMD;
  358. }
  359. static ABC_CALLBACK(abcdisk_callback_rst)
  360. {
  361. struct ctl_state * const state = container_of(dev, struct ctl_state, iodev);
  362. state->pending |= PEND_RESET;
  363. }
  364. static char abcdisk_80_800[] = "/abcdisk.800/";
  365. static const char * const disk_pfx[] = {
  366. abcdisk_80_800, "/abcdisk/", "/abcdisk.", "/", NULL
  367. };
  368. static void init_drives(struct ctl_state *state)
  369. {
  370. char *p80;
  371. int i;
  372. /* .80/ or .800/ for the first entry */
  373. p80 = abcdisk_80_800 + 10 + is_abc800();
  374. p80[0] = '0';
  375. p80[1] = '/';
  376. p80[2] = '\0';
  377. for (i = 0; i < 8; i++) {
  378. struct drive_state *drv = &state->drv[i];
  379. unsigned int filesec;
  380. const char * const *pfx;
  381. snprintf(drv->name, sizeof drv->name, "%-.2s%c",
  382. state->params->name, i + '0');
  383. for (pfx = disk_pfx; *pfx; pfx++) {
  384. char filename_buf[64];
  385. snprintf(filename_buf, sizeof filename_buf,
  386. "%s%s", *pfx, drv->name);
  387. if (!mount_drive(drv, state, filename_buf))
  388. break;
  389. }
  390. }
  391. state->initialized = true;
  392. }
  393. static void do_next_command(struct ctl_state *state)
  394. {
  395. struct drive_state * const drv = cur_drv_mutable(state);
  396. uint8_t *buf = cur_buf(state);
  397. #if 0
  398. con_printf("%-3s: cmd %02x %02x %02x %02x\n",
  399. drv->name, state->k[0], state->k[1],
  400. state->k[2], state->k[3]);
  401. #endif
  402. if (state->k[0] & 0x01) {
  403. /* READ SECTOR */
  404. if (!(drv->flags & DF_MOUNTED)) {
  405. disk_set_error(state, DISK_NOT_READY);
  406. } else if (!cur_sector_valid(state)) {
  407. disk_set_error(state, OUT_OF_RANGE);
  408. } else {
  409. UINT rlen = 0;
  410. FRESULT rv;
  411. set_led(LED_DISKIO, true);
  412. abc_set_inp_status(&state->iodev, AS_READING|AS_READY);
  413. rv = f_lseek(&drv->file, file_pos(state));
  414. if (rv == FR_OK)
  415. rv = f_read(&drv->file, buf, 256, &rlen);
  416. if (rv != FR_OK || rlen != 256) {
  417. disk_set_error(state, CRC_ERROR);
  418. }
  419. }
  420. state->k[0] &= ~0x01; /* Command done */
  421. }
  422. if (state->k[0] & 0x02) {
  423. /* SECTOR TO HOST */
  424. state->k[0] &= ~0x02; /* Command done */
  425. state->iodev.callback_mask |= 1 << 8;
  426. abc_setup_inp_queue(&state->iodev, buf, 256, AS_READY);
  427. return;
  428. }
  429. if (state->k[0] & 0x04) {
  430. /* SECTOR FROM HOST */
  431. state->k[0] &= ~0x04; /* Command done */
  432. state->iodev.callback_mask |= 1 << 0;
  433. abc_setup_out_queue(&state->iodev, buf, 256, AS_WRITE|AS_READY);
  434. return;
  435. }
  436. if (state->k[0] & 0x08) {
  437. /* WRITE SECTOR */
  438. if (!(drv->flags & DF_MOUNTED)) {
  439. disk_set_error(state, DISK_NOT_READY);
  440. } else if (drv->flags & DF_READONLY) {
  441. disk_set_error(state, WRITE_PROTECT);
  442. } else if (!cur_sector_valid(state)) {
  443. disk_set_error(state, OUT_OF_RANGE);
  444. } else {
  445. UINT wlen = 0;
  446. FRESULT rv;
  447. set_led(LED_DISKIO, true);
  448. rv = f_lseek(&drv->file, file_pos(state));
  449. if (rv == FR_OK) {
  450. drv->flags |= DF_DIRTY;
  451. rv = f_write(&drv->file, buf, 256, &wlen);
  452. }
  453. if (rv != FR_OK || wlen != 256)
  454. disk_set_error(state, WRITE_FAULT);
  455. }
  456. state->k[0] &= ~0x08; /* Command done */
  457. }
  458. #if FORMAT_SUPPORT
  459. /* This code needs additional work */
  460. if (state->k[0] & 0x10 && state->k[1] & 0x08) {
  461. state->out_ptr = 0;
  462. /* FORMAT */
  463. if (!drv->hf) {
  464. state->error = 0x80; /* Not ready */
  465. } else if (!file_wrok(hf)) {
  466. state->error = 0x40; /* Write protect */
  467. } else {
  468. unsigned int s, c0, c1, s0, s1;
  469. unsigned int cylsec = state->s * state->h;
  470. uint8_t data[256];
  471. unsigned int fmtsec, filesec;
  472. /* Sector count produced by format */
  473. fmtsec = state->params->maxsectors;
  474. /* For non-MO-drives, this seems to be internally generated */
  475. memset(data, 0x40, 256);
  476. if (state->fmtdata_in_buf) {
  477. /*
  478. * MO drives put the sector image in the buffers, for
  479. * backwards compatibility and to support single density.
  480. *
  481. * Right before the F7 header CRC opcode is a density byte;
  482. * 00 for single, and 01 for double. The data begins after
  483. * a byte of FB.
  484. */
  485. bool single = false;
  486. const uint8_t *p, *ep;
  487. ep = state->buf[1];
  488. for (p = state->buf[0]+1; p < ep; p++) {
  489. if (*p == 0xf7)
  490. single = (p[-1] == 0);
  491. if (*p == 0xfb)
  492. break;
  493. }
  494. fmtsec >>= single;
  495. if (*p++ == 0xfb) { /* Data block found */
  496. if (single) {
  497. /* Really two 128-byte sectors! */
  498. memcpy(data, p, 128);
  499. memcpy(data+128, p, 128);
  500. } else {
  501. memcpy(data, p, 256);
  502. }
  503. }
  504. }
  505. /*
  506. * Adjust the size of the accessible device to the smallest
  507. * of the physical file and the formatted size
  508. */
  509. filesec = drv->hf->filesize >> 8;
  510. drv->sectors = (filesec && filesec < fmtsec) ? filesec : fmtsec;
  511. /*
  512. * k2 and k3 contain the first and last cylinder numbers to
  513. * format, inclusively. The last cylinder may be partial due
  514. * to virtual remapping, e.g. for sf floppies.
  515. */
  516. c0 = state->k[2];
  517. s0 = c0 * cylsec;
  518. c1 = state->k[3] + 1;
  519. s1 = c1 * cylsec;
  520. if (tracing(TRACE_DISK)) {
  521. fprintf(tracef, "%s: formatting cyl %u..%u, sectors %u..%u\n",
  522. drv->name, c0, c1-1, s0, s1-1);
  523. }
  524. clearerr(hf->f);
  525. state->error = 0;
  526. for (s = s0; s < s1; s++) {
  527. unsigned int ps = virt2phys(drv, s);
  528. if (ps >= drv->sectors) {
  529. state->error |= 0x02; /* Track 0/Lost data? */
  530. break;
  531. } else if (hf->map) {
  532. memcpy(hf->map + (ps << 8), data, 256);
  533. } else {
  534. fseek(hf->f, ps << 8, SEEK_SET);
  535. fwrite(data, 1, 256, hf->f);
  536. }
  537. }
  538. if (ferror(hf->f))
  539. state->error |= 0x20; /* Write fault */
  540. }
  541. state->k[1] &= ~0x08;
  542. }
  543. if (!(state->k[1] & 0x38))
  544. state->k[0] &= ~0x10;
  545. #else
  546. /* No FORMAT support */
  547. state->k[0] &= ~0x10;
  548. #endif
  549. state->k[0] &= ~0xe0; /* Unimplemented commands */
  550. disk_start_command(state);
  551. }
  552. static FATFS sd_fs;
  553. static bool sd_mounted;
  554. static int mount_disk(void)
  555. {
  556. FRESULT rv;
  557. char label[128];
  558. uint32_t volid, freeclust;
  559. FATFS *fs;
  560. set_led(LED_DISKIO, true);
  561. rv = f_mount(&sd_fs, "", 1);
  562. if (rv != FR_OK) {
  563. con_printf("sdcard: no volume found\n");
  564. set_led(LED_DISKIO, false);
  565. return -1;
  566. }
  567. sd_mounted = true;
  568. label[0] = '\0';
  569. volid = 0;
  570. f_getlabel("", label, &volid);
  571. con_printf("sdcard: volume found, label \"%s\", volid %08x\n", label, volid);
  572. freeclust = 0;
  573. f_getfree("", &freeclust, &fs);
  574. con_printf("sdcard: %u/%u clusters free, clusters = %u bytes\n",
  575. freeclust, fs->n_fatent - 2, fs->csize << 9);
  576. /* Check for firmware update image and install if it exists */
  577. rom_flash_from_sdcard();
  578. return 0;
  579. }
  580. #define SYNC_TIME (1*TIMER_HZ) /* 1 s */
  581. /* Called from the main loop */
  582. void __hot abcdisk_io_poll(void)
  583. {
  584. static uint32_t last_sync;
  585. static uint32_t last_timer = -1U;
  586. static uint32_t prev_abc_status = -1U;
  587. uint32_t abc_status_change;
  588. uint32_t now = timer_count();
  589. bool need_sync = false;
  590. uint32_t abc_status = ABC_STATUS & ABC_STATUS_LIVE;
  591. bool unmount_all = false;
  592. bool reset_all = false;
  593. if (now != last_timer) {
  594. /*
  595. * Periodically try to initialize the SD card if we are waiting
  596. * for it. The disk cache, however, will be initialized when fatfs
  597. * tries to mount the device.
  598. */
  599. if (sdc.status & STA_NOINIT) {
  600. if (!(sdcard_init() & STA_NOINIT))
  601. mount_disk();
  602. unmount_all = true;
  603. } else if (sdcard_present_poll() & STA_NOINIT) {
  604. unmount_all = true;
  605. } else {
  606. if ((now - last_sync) >= SYNC_TIME) {
  607. need_sync = true;
  608. last_sync = now;
  609. }
  610. }
  611. last_timer = now;
  612. }
  613. /* Allow configuration to override */
  614. if (is_abc800())
  615. abc_status |= ABC_STATUS_800;
  616. abc_status_change = abc_status ^ prev_abc_status;
  617. if (unlikely(abc_status_change)) {
  618. const char *host;
  619. prev_abc_status = abc_status;
  620. set_led(LED_ABCBUS, !!(abc_status & ABC_STATUS_LIVE));
  621. con_puts("ABC-bus host: ");
  622. con_puts(abc_status & ABC_STATUS_800 ? "ABC800" : "ABC80");
  623. con_puts(abc_status & ABC_STATUS_LIVE ? " (online)\n" : " (offline)\n");
  624. unmount_all = !!(abc_status_change & ABC_STATUS_800);
  625. reset_all = true;
  626. need_sync = true;
  627. }
  628. for (int i = 0; i < CONTROLLER_TYPES; i++) {
  629. struct ctl_state * const state = &controllers[i];
  630. enum pending pending = 0;
  631. if (unmount_all && state->initialized) {
  632. unmount_drives(state);
  633. state->initialized = false;
  634. } else if (!state->initialized && !(sdc.status & STA_NOINIT)) {
  635. init_drives(state);
  636. }
  637. if (reset_all)
  638. disk_reset_state(state);
  639. if (abc_status & ABC_STATUS_LIVE) {
  640. mask_irq(ABC_IRQ);
  641. pending = state->pending;
  642. state->pending = 0;
  643. unmask_irq(ABC_IRQ);
  644. if (pending & (PEND_RESET|PEND_STARTCMD))
  645. disk_reset_state(state);
  646. else if (pending & PEND_IO)
  647. do_next_command(state);
  648. }
  649. if (state->initialized && (need_sync || (pending & PEND_RESET)))
  650. sync_drives(state);
  651. }
  652. if (need_sync) {
  653. /* Did we sync drives? Clear LED. */
  654. set_led(LED_DISKIO, false);
  655. }
  656. }
  657. /*
  658. * Called during initialization. Don't initialize the SD card here;
  659. * it will take too long and ABC will time out claiming no drives present.
  660. */
  661. void abcdisk_init(void)
  662. {
  663. static const struct abc_dev iodev_template = {
  664. .callback_mask = IDLE_CALLBACK_MASK,
  665. .inp_en = 3,
  666. .status_first_out_mask = (uint8_t)~0x80,
  667. .status_first_inp_mask = (uint8_t)~0x80,
  668. .callback_out[0] = abcdisk_callback_out_inp,
  669. .callback_inp[0] = abcdisk_callback_out_inp,
  670. .callback_out[2] = abcdisk_callback_restart,
  671. .callback_out[4] = abcdisk_callback_rst, /* C3# = local reset */
  672. .callback_rst = abcdisk_callback_rst
  673. };
  674. for (size_t i = 0; i < CONTROLLER_TYPES; i++) {
  675. struct ctl_state * const state = &controllers[i];
  676. state->params = &parameters[i];
  677. state->iodev = iodev_template;
  678. state->iodev.name = state->params->name;
  679. disk_reset_state(state);
  680. }
  681. abcdisk_config();
  682. }
  683. /*
  684. * Called during initialization; can also be called on reconfig.
  685. */
  686. void abcdisk_config(void)
  687. {
  688. for (size_t i = 0; i < CONTROLLER_TYPES; i++) {
  689. struct ctl_state * const state = &controllers[i];
  690. unsigned int devsel = getvar_uint(state->params->devsel);
  691. if (!getvar_bool(state->params->enable))
  692. devsel = DEVSEL_NONE;
  693. abc_register(&state->iodev, devsel);
  694. }
  695. }
  696. /*
  697. * Shut down the disk subsystem for reboot
  698. */
  699. void abcdisk_shutdown(void)
  700. {
  701. if (!sd_mounted)
  702. return; /* Nothing to do */
  703. for (int i = 0; i < CONTROLLER_TYPES; i++) {
  704. struct ctl_state * const state = &controllers[i];
  705. if (state->initialized)
  706. unmount_drives(state);
  707. }
  708. /* Unmount the SD card filesystem */
  709. f_unmount("");
  710. /* Check one last time to see if anything needs to be written out */
  711. disk_ioctl(0, CTRL_SYNC, NULL);
  712. sd_mounted = false;
  713. }