PageRenderTime 119ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/src/catweasel.c

https://github.com/amigrave/PUAE
C | 776 lines | 675 code | 95 blank | 6 comment | 144 complexity | e59627eec94de80e90b069f98031fd07 MD5 | raw file
  1. #include "sysconfig.h"
  2. #include "sysdeps.h"
  3. #ifdef CATWEASEL
  4. #include "options.h"
  5. #include "memory.h"
  6. #include "ioport.h"
  7. #include "catweasel.h"
  8. #include "uae.h"
  9. struct catweasel_contr cwc;
  10. static int cwhsync;
  11. static int handshake;
  12. void catweasel_hsync (void)
  13. {
  14. if (cwhsync <= 0)
  15. return;
  16. cwhsync--;
  17. if (cwhsync == 0) {
  18. if (handshake)
  19. ioport_write (currprefs.catweasel_io + 0xd0, 0);
  20. handshake = 0;
  21. }
  22. }
  23. int catweasel_read_joystick (uae_u8 *dir, uae_u8 *buttons)
  24. {
  25. if (cwc.type != CATWEASEL_TYPE_MK3)
  26. return 0;
  27. *dir = ioport_read (currprefs.catweasel_io + 0xc0);
  28. *buttons = ioport_read (currprefs.catweasel_io + 0xc8);
  29. return 1;
  30. }
  31. int catweasel_read_keyboard (uae_u8 *keycode)
  32. {
  33. uae_u8 v;
  34. if (cwc.type != CATWEASEL_TYPE_MK3)
  35. return 0;
  36. v = ioport_read (currprefs.catweasel_io + 0xd4);
  37. if (!(v & 0x80))
  38. return 0;
  39. if (handshake)
  40. return 0;
  41. *keycode = ioport_read (currprefs.catweasel_io + 0xd0);
  42. ioport_write (currprefs.catweasel_io + 0xd0, 0);
  43. handshake = 1;
  44. cwhsync = 10;
  45. return 1;
  46. }
  47. uae_u32 catweasel_do_bget (uaecptr addr)
  48. {
  49. if (cwc.type == CATWEASEL_TYPE_MK3) {
  50. if ((currprefs.catweasel_io & 3) == 0 && addr >= 0xc0 && addr <= 0xfc)
  51. return ioport_read (currprefs.catweasel_io + addr);
  52. } else {
  53. if (addr >= currprefs.catweasel_io && addr <= currprefs.catweasel_io + 8) {
  54. return ioport_read (addr & 0x3ff);
  55. } else if(addr >= 0x10000 + currprefs.catweasel_io && addr <= 0x10000 + currprefs.catweasel_io) {
  56. return ioport_read (addr & 0x3ff);
  57. } else if ((addr & 0x3ff) < 0x200 || (addr & 0x3ff) >= 0x400) {
  58. write_log ("catweasel_bget @%08.8X!\n",addr);
  59. }
  60. }
  61. return 0;
  62. }
  63. void catweasel_do_bput (uaecptr addr, uae_u32 b)
  64. {
  65. if (cwc.type == CATWEASEL_TYPE_MK3) {
  66. if ((currprefs.catweasel_io & 3) == 0 && addr >= 0xc0 && addr <= 0xfc)
  67. ioport_write (currprefs.catweasel_io + addr, b);
  68. } else {
  69. if (addr >= currprefs.catweasel_io && addr <= currprefs.catweasel_io + 8) {
  70. ioport_write (addr & 0x3ff, b);
  71. } else if(addr >= 0x10000 + currprefs.catweasel_io && addr <= 0x10000 + currprefs.catweasel_io) {
  72. ioport_write (addr & 0x3ff, b);
  73. } else if ((addr & 0x3ff) < 0x200 || (addr & 0x3ff) >= 0x400) {
  74. write_log ("catweasel_bput @%08.8X=%02.2X!\n",addr,b);
  75. }
  76. }
  77. }
  78. int catweasel_init (void)
  79. {
  80. if (!currprefs.catweasel_io)
  81. return 0;
  82. if (!ioport_init ())
  83. return 0;
  84. cwc.type = currprefs.catweasel_io >= 0x400 ? CATWEASEL_TYPE_MK3 : CATWEASEL_TYPE_MK1;
  85. cwc.iobase = currprefs.catweasel_io;
  86. catweasel_init_controller (&cwc);
  87. return 1;
  88. }
  89. void catweasel_free (void)
  90. {
  91. if (!currprefs.catweasel_io)
  92. return;
  93. ioport_free ();
  94. }
  95. #define outb(v,port) ioport_write(port,v)
  96. #define inb(port) ioport_read(port)
  97. #define LONGEST_TRACK 16000
  98. static uae_u8 mfmbuf[LONGEST_TRACK * 4];
  99. static uae_u8 tmpmfmbuffer[LONGEST_TRACK * 2];
  100. static int bitshiftcompare(uae_u8 *src,int bit,int len,uae_u8 *comp)
  101. {
  102. uae_u8 b;
  103. int ones,zeros,len2;
  104. ones=zeros=0;
  105. len2=len;
  106. while(len--) {
  107. b = (comp[0] << bit) | (comp[1] >> (8 - bit));
  108. if(b != *src) return 1;
  109. if(b==0x00) zeros++;
  110. if(b==0xff) ones++;
  111. src++;
  112. comp++;
  113. }
  114. if(ones==len2||zeros==len2) return 1;
  115. return 0;
  116. }
  117. static uae_u8 *mergepieces(uae_u8 *start,int len,int bits,uae_u8 *sync)
  118. {
  119. uae_u8 *dst=tmpmfmbuffer;
  120. uae_u8 b;
  121. int size;
  122. int shift;
  123. size=len-(sync-start);
  124. memcpy(dst,sync,size);
  125. dst+=size;
  126. b=start[len];
  127. b&=~(255>>bits);
  128. b|=start[0]>>bits;
  129. *dst++=b;
  130. shift=8-bits;
  131. while(start<=sync+2000) {
  132. *dst++=(start[0]<<shift)|(start[1]>>(8-shift));
  133. start++;
  134. }
  135. return tmpmfmbuffer;
  136. }
  137. #define SCANOFFSET 1 /* scanning range in bytes, -SCANOFFSET to SCANOFFSET */
  138. #define SCANOFFSET2 20
  139. #define SCANLENGHT 200 /* scanning length in bytes */
  140. static uae_u8* scantrack(uae_u8 *sync1,uae_u8 *sync2,int *trackbytes,int *trackbits)
  141. {
  142. int i,bits,bytes,matched;
  143. uae_u8 *sync2bak=sync2;
  144. sync1+=SCANOFFSET2;
  145. sync2+=SCANOFFSET2;
  146. while(sync1 < sync2bak - 2*SCANOFFSET - SCANOFFSET2 - SCANLENGHT) {
  147. matched=0x7fff;
  148. for(i=0;i<2*SCANOFFSET*8;i++) {
  149. bits=i&7;
  150. bytes=-SCANOFFSET+(i>>3);
  151. if(!bitshiftcompare(sync1,bits,SCANLENGHT,sync2+bytes)) {
  152. if(matched==0x7fff) {
  153. matched=i;
  154. } else {
  155. break;
  156. }
  157. }
  158. }
  159. if(matched!=0x7fff && i>=2*SCANOFFSET*8) {
  160. bits=matched&7;
  161. bytes=-SCANOFFSET+(matched>>3);
  162. *trackbytes=sync2+bytes-sync1;
  163. *trackbits=bits;
  164. return mergepieces(sync1,*trackbytes,*trackbits,sync2bak);
  165. }
  166. sync1++;
  167. sync2++;
  168. }
  169. return 0;
  170. }
  171. static unsigned char threshtab[128];
  172. static void codec_makethresh(int trycnt, const unsigned char *origt, unsigned char *t, int numthresh)
  173. {
  174. static unsigned char tab[10] = { 0, 0, 0, 0, -1, -2, 1, 2, -1, 1 };
  175. if (trycnt >= sizeof (tab))
  176. trycnt = sizeof (tab) - 1;
  177. while(numthresh--)
  178. t[numthresh] = origt[numthresh] + tab[trycnt];
  179. }
  180. static void codec_init_threshtab(int trycnt, const unsigned char *origt)
  181. {
  182. static unsigned char old_thresholds[2] = { 0, 0 };
  183. unsigned char t[2];
  184. int a, i;
  185. codec_makethresh(trycnt, origt, t, 2);
  186. if(*(unsigned short*)t == *(unsigned short*)old_thresholds)
  187. return;
  188. for(i=0,a=2; i<128; i++) {
  189. if(i == t[0] || i == t[1])
  190. a++;
  191. threshtab[i] = a;
  192. }
  193. *(unsigned short*)&old_thresholds = *(unsigned short*)t;
  194. }
  195. static __inline__ void CWSetCReg(catweasel_contr *c, unsigned char clear, unsigned char set)
  196. {
  197. c->control_register = (c->control_register & ~clear) | set;
  198. outb(c->control_register, c->io_sr);
  199. }
  200. static void CWTriggerStep(catweasel_contr *c)
  201. {
  202. CWSetCReg(c, c->crm_step, 0);
  203. CWSetCReg(c, 0, c->crm_step);
  204. }
  205. void catweasel_init_controller(catweasel_contr *c)
  206. {
  207. int i, j;
  208. if(!c->iobase)
  209. return;
  210. switch(c->type) {
  211. case CATWEASEL_TYPE_MK1:
  212. c->crm_sel0 = 1 << 5;
  213. c->crm_sel1 = 1 << 4;
  214. c->crm_mot0 = 1 << 3;
  215. c->crm_mot1 = 1 << 7;
  216. c->crm_dir = 1 << 1;
  217. c->crm_step = 1 << 0;
  218. c->srm_trk0 = 1 << 4;
  219. c->srm_dchg = 1 << 5;
  220. c->srm_writ = 1 << 1;
  221. c->io_sr = c->iobase + 2;
  222. c->io_mem = c->iobase;
  223. break;
  224. case CATWEASEL_TYPE_MK3:
  225. c->crm_sel0 = 1 << 2;
  226. c->crm_sel1 = 1 << 3;
  227. c->crm_mot0 = 1 << 1;
  228. c->crm_mot1 = 1 << 5;
  229. c->crm_dir = 1 << 4;
  230. c->crm_step = 1 << 7;
  231. c->srm_trk0 = 1 << 2;
  232. c->srm_dchg = 1 << 5;
  233. c->srm_writ = 1 << 6;
  234. c->srm_dskready = 1 << 4;
  235. c->io_sr = c->iobase + 0xe8;
  236. c->io_mem = c->iobase + 0xe0;
  237. break;
  238. default:
  239. return;
  240. }
  241. c->control_register = 255;
  242. /* select all drives, step inside */
  243. CWSetCReg(c, c->crm_dir | c->crm_sel0 | c->crm_sel1, 0);
  244. for(i=0;i<2;i++) {
  245. c->drives[i].number = i;
  246. c->drives[i].contr = c;
  247. c->drives[i].diskindrive = 0;
  248. /* select only the respective drive, step to track 0 */
  249. if(i == 0) {
  250. CWSetCReg(c, c->crm_sel0, c->crm_dir | c->crm_sel1);
  251. } else {
  252. CWSetCReg(c, c->crm_sel1, c->crm_dir | c->crm_sel0);
  253. }
  254. for(j = 0; j < 86 && (inb(c->io_sr) & c->srm_trk0); j++) {
  255. CWTriggerStep(c);
  256. sleep_millis(6);
  257. }
  258. if(j < 86) {
  259. c->drives[i].type = 1;
  260. c->drives[i].track = 0;
  261. } else {
  262. c->drives[i].type = 0;
  263. }
  264. }
  265. c->drives[0].sel = c->crm_sel0;
  266. c->drives[0].mot = c->crm_mot0;
  267. c->drives[1].sel = c->crm_sel1;
  268. c->drives[1].mot = c->crm_mot1;
  269. CWSetCReg(c, 0, c->crm_sel0 | c->crm_sel1); /* deselect all drives */
  270. }
  271. void catweasel_free_controller(catweasel_contr *c)
  272. {
  273. if(!c->iobase)
  274. return;
  275. /* all motors off, deselect all drives */
  276. CWSetCReg(c, 0, c->crm_mot0 | c->crm_mot1 | c->crm_sel0 | c->crm_sel1);
  277. }
  278. void catweasel_set_motor(catweasel_drive *d, int on)
  279. {
  280. CWSetCReg(d->contr, d->sel, 0);
  281. if (on)
  282. CWSetCReg(d->contr, d->mot, 0);
  283. else
  284. CWSetCReg(d->contr, 0, d->mot);
  285. CWSetCReg(d->contr, 0, d->sel);
  286. }
  287. int catweasel_step(catweasel_drive *d, int dir)
  288. {
  289. catweasel_contr *c = d->contr;
  290. CWSetCReg(c, d->sel, 0);
  291. if (dir > 0)
  292. CWSetCReg(c, c->crm_dir, 0);
  293. else
  294. CWSetCReg(c, 0, c->crm_dir);
  295. CWTriggerStep (c);
  296. CWSetCReg(c, 0, d->sel);
  297. d->track += dir > 0 ? 1 : -1;
  298. return 1;
  299. }
  300. int catweasel_disk_changed(catweasel_drive *d)
  301. {
  302. int ret;
  303. CWSetCReg(d->contr, d->sel, 0);
  304. ret = (inb(d->contr->io_sr) & d->contr->srm_dchg) ? 0 : 1;
  305. CWSetCReg(d->contr, 0, d->sel);
  306. return ret;
  307. }
  308. int catweasel_diskready(catweasel_drive *d)
  309. {
  310. int ret;
  311. CWSetCReg(d->contr, d->sel, 0);
  312. ret = (inb(d->contr->io_sr) & d->contr->srm_dskready) ? 0 : 1;
  313. CWSetCReg(d->contr, 0, d->sel);
  314. return ret;
  315. }
  316. int catweasel_track0(catweasel_drive *d)
  317. {
  318. int ret;
  319. CWSetCReg(d->contr, d->sel, 0);
  320. ret = (inb(d->contr->io_sr) & d->contr->srm_trk0) ? 0 : 1;
  321. CWSetCReg(d->contr, 0, d->sel);
  322. if (ret)
  323. d->track = 0;
  324. return ret;
  325. }
  326. int catweasel_write_protected(catweasel_drive *d)
  327. {
  328. int ret;
  329. CWSetCReg(d->contr, d->sel, 0);
  330. ret = !(inb(d->contr->io_sr) & 8);
  331. CWSetCReg(d->contr, 0, d->sel);
  332. return ret;
  333. }
  334. uae_u8 catweasel_read_byte(catweasel_drive *d)
  335. {
  336. return inb(d->contr->io_mem);
  337. }
  338. static const unsigned char amiga_thresholds[] = { 0x22, 0x30 }; // 27, 38 for 5.25"
  339. #define FLOPPY_WRITE_LEN 6250
  340. #define MFMMASK 0x55555555
  341. static uae_u32 getmfmlong (uae_u16 * mbuf)
  342. {
  343. return (uae_u32)(((*mbuf << 16) | *(mbuf + 1)) & MFMMASK);
  344. }
  345. static int drive_write_adf_amigados (uae_u16 *mbuf, uae_u16 *mend, uae_u8 *writebuffer, int track)
  346. {
  347. int i, secwritten = 0;
  348. uae_u32 odd, even, chksum, id, dlong;
  349. uae_u8 *secdata;
  350. uae_u8 secbuf[544];
  351. char sectable[22];
  352. int num_sectors = 11;
  353. int ec = 0;
  354. memset (sectable, 0, sizeof (sectable));
  355. mend -= (4 + 16 + 8 + 512);
  356. while (secwritten < num_sectors) {
  357. int trackoffs;
  358. do {
  359. while (*mbuf++ != 0x4489) {
  360. if (mbuf >= mend) {
  361. ec = 1;
  362. goto err;
  363. }
  364. }
  365. } while (*mbuf++ != 0x4489);
  366. odd = getmfmlong (mbuf);
  367. even = getmfmlong (mbuf + 2);
  368. mbuf += 4;
  369. id = (odd << 1) | even;
  370. trackoffs = (id & 0xff00) >> 8;
  371. if (trackoffs > 10) {
  372. ec = 2;
  373. goto err;
  374. }
  375. chksum = odd ^ even;
  376. for (i = 0; i < 4; i++) {
  377. odd = getmfmlong (mbuf);
  378. even = getmfmlong (mbuf + 8);
  379. mbuf += 2;
  380. dlong = (odd << 1) | even;
  381. if (dlong) {
  382. ec = 6;
  383. goto err;
  384. }
  385. chksum ^= odd ^ even;
  386. } /* could check here if the label is nonstandard */
  387. mbuf += 8;
  388. odd = getmfmlong (mbuf);
  389. even = getmfmlong (mbuf + 2);
  390. mbuf += 4;
  391. if (((odd << 1) | even) != chksum) {
  392. ec = 3;
  393. goto err;
  394. }
  395. odd = (id & 0x00ff0000) >> 16;
  396. if (odd != track) {
  397. ec = 7;
  398. goto err;
  399. }
  400. odd = getmfmlong (mbuf);
  401. even = getmfmlong (mbuf + 2);
  402. mbuf += 4;
  403. chksum = (odd << 1) | even;
  404. secdata = secbuf + 32;
  405. for (i = 0; i < 128; i++) {
  406. odd = getmfmlong (mbuf);
  407. even = getmfmlong (mbuf + 256);
  408. mbuf += 2;
  409. dlong = (odd << 1) | even;
  410. *secdata++ = dlong >> 24;
  411. *secdata++ = dlong >> 16;
  412. *secdata++ = dlong >> 8;
  413. *secdata++ = dlong;
  414. chksum ^= odd ^ even;
  415. }
  416. mbuf += 256;
  417. if (chksum) {
  418. ec = 4;
  419. goto err;
  420. }
  421. sectable[trackoffs] = 1;
  422. secwritten++;
  423. memcpy (writebuffer + trackoffs * 512, secbuf + 32, 512);
  424. }
  425. if (secwritten == 0 || secwritten < 0) {
  426. ec = 5;
  427. goto err;
  428. }
  429. return 0;
  430. err:
  431. write_log ("mfm decode error %d. secwritten=%d\n", ec, secwritten);
  432. for (i = 0; i < num_sectors; i++)
  433. write_log ("%d:%d ", i, sectable[i]);
  434. write_log ("\n");
  435. return ec;
  436. }
  437. static void mfmcode (uae_u16 * mfm, int words)
  438. {
  439. uae_u32 lastword = 0;
  440. while (words--) {
  441. uae_u32 v = *mfm;
  442. uae_u32 lv = (lastword << 16) | v;
  443. uae_u32 nlv = 0x55555555 & ~lv;
  444. uae_u32 mfmbits = (nlv << 1) & (nlv >> 1);
  445. *mfm++ = v | mfmbits;
  446. lastword = v;
  447. }
  448. }
  449. #define FLOPPY_GAP_LEN 360
  450. static int amigados_mfmcode (uae_u8 *src, uae_u16 *dst, int num_secs, int track)
  451. {
  452. int sec;
  453. memset (dst, 0xaa, FLOPPY_GAP_LEN * 2);
  454. for (sec = 0; sec < num_secs; sec++) {
  455. uae_u8 secbuf[544];
  456. int i;
  457. uae_u16 *mfmbuf = dst + 544 * sec + FLOPPY_GAP_LEN;
  458. uae_u32 deven, dodd;
  459. uae_u32 hck = 0, dck = 0;
  460. secbuf[0] = secbuf[1] = 0x00;
  461. secbuf[2] = secbuf[3] = 0xa1;
  462. secbuf[4] = 0xff;
  463. secbuf[5] = track;
  464. secbuf[6] = sec;
  465. secbuf[7] = num_secs - sec;
  466. for (i = 8; i < 24; i++)
  467. secbuf[i] = 0;
  468. mfmbuf[0] = mfmbuf[1] = 0xaaaa;
  469. mfmbuf[2] = mfmbuf[3] = 0x4489;
  470. memcpy (secbuf + 32, src + sec * 512, 512);
  471. deven = ((secbuf[4] << 24) | (secbuf[5] << 16)
  472. | (secbuf[6] << 8) | (secbuf[7]));
  473. dodd = deven >> 1;
  474. deven &= 0x55555555;
  475. dodd &= 0x55555555;
  476. mfmbuf[4] = dodd >> 16;
  477. mfmbuf[5] = dodd;
  478. mfmbuf[6] = deven >> 16;
  479. mfmbuf[7] = deven;
  480. for (i = 8; i < 48; i++)
  481. mfmbuf[i] = 0xaaaa;
  482. for (i = 0; i < 512; i += 4) {
  483. deven = ((secbuf[i + 32] << 24) | (secbuf[i + 33] << 16)
  484. | (secbuf[i + 34] << 8) | (secbuf[i + 35]));
  485. dodd = deven >> 1;
  486. deven &= 0x55555555;
  487. dodd &= 0x55555555;
  488. mfmbuf[(i >> 1) + 32] = dodd >> 16;
  489. mfmbuf[(i >> 1) + 33] = dodd;
  490. mfmbuf[(i >> 1) + 256 + 32] = deven >> 16;
  491. mfmbuf[(i >> 1) + 256 + 33] = deven;
  492. }
  493. for (i = 4; i < 24; i += 2)
  494. hck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1];
  495. deven = dodd = hck;
  496. dodd >>= 1;
  497. mfmbuf[24] = dodd >> 16;
  498. mfmbuf[25] = dodd;
  499. mfmbuf[26] = deven >> 16;
  500. mfmbuf[27] = deven;
  501. for (i = 32; i < 544; i += 2)
  502. dck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1];
  503. deven = dodd = dck;
  504. dodd >>= 1;
  505. mfmbuf[28] = dodd >> 16;
  506. mfmbuf[29] = dodd;
  507. mfmbuf[30] = deven >> 16;
  508. mfmbuf[31] = deven;
  509. mfmcode (mfmbuf + 4, 544 - 4);
  510. }
  511. return (num_secs * 544 + FLOPPY_GAP_LEN) * 2 * 8;
  512. }
  513. static uae_u16 amigamfmbuffer[LONGEST_TRACK];
  514. static uae_u8 amigabuffer[512*22];
  515. /* search and align to 0x4489 WORDSYNC markers */
  516. static int isamigatrack(uae_u8 *mfmdata, uae_u8 *mfmdatae, uae_u16 *mfmdst, int track)
  517. {
  518. uae_u16 *dst = amigamfmbuffer;
  519. int len;
  520. int shift, syncshift, sync,ret;
  521. uae_u32 l;
  522. uae_u16 w;
  523. sync = syncshift = shift = 0;
  524. len = (mfmdatae - mfmdata) * 8;
  525. if (len > LONGEST_TRACK * 8)
  526. len = LONGEST_TRACK * 8;
  527. while (len--) {
  528. l = (mfmdata[0] << 16) | (mfmdata[1] << 8) | (mfmdata[2] << 0);
  529. w = l >> (8 - shift);
  530. if (w == 0x4489) {
  531. sync = 1;
  532. syncshift = 0;
  533. }
  534. if (sync) {
  535. if (syncshift == 0) *dst++ = w;
  536. syncshift ++;
  537. if (syncshift == 16) syncshift = 0;
  538. }
  539. shift++;
  540. if (shift == 8) {
  541. mfmdata++;
  542. shift = 0;
  543. }
  544. }
  545. if (sync) {
  546. ret=drive_write_adf_amigados (amigamfmbuffer, dst, amigabuffer, track);
  547. if(!ret)
  548. return amigados_mfmcode (amigabuffer, mfmdst, 11, track);
  549. write_log ("decode error %d\n", ret);
  550. } else {
  551. write_log ("decode error: no sync found\n");
  552. }
  553. return 0;
  554. }
  555. int catweasel_fillmfm (catweasel_drive *d, uae_u16 *mfm, int side, int clock, int rawmode)
  556. {
  557. int i, j, oldsync, syncs[10], synccnt, endcnt;
  558. uae_u32 tt1 = 0, tt2 = 0;
  559. uae_u8 *p1;
  560. int bytes = 0, bits = 0;
  561. static int lasttrack, trycnt;
  562. if (cwc.type == 0)
  563. return 0;
  564. if (d->contr->control_register & d->mot)
  565. return 0;
  566. if (!catweasel_read (d, side, 1, rawmode))
  567. return 0;
  568. if(d->contr->type == CATWEASEL_TYPE_MK1) {
  569. inb(d->contr->iobase + 1);
  570. inb(d->contr->io_mem); /* ignore first byte */
  571. } else {
  572. outb(0, d->contr->iobase + 0xe4);
  573. }
  574. catweasel_read_byte (d);
  575. if (lasttrack == d->track)
  576. trycnt++;
  577. else
  578. trycnt = 0;
  579. lasttrack = d->track;
  580. codec_init_threshtab(trycnt, amiga_thresholds);
  581. i = 0; j = 0;
  582. synccnt = 0;
  583. oldsync = -1;
  584. endcnt = 0;
  585. while (j < LONGEST_TRACK * 4) {
  586. uae_u8 b = catweasel_read_byte (d);
  587. if (b >= 250) {
  588. if (b == 255 - endcnt) {
  589. endcnt++;
  590. if (endcnt == 5)
  591. break;
  592. } else
  593. endcnt = 0;
  594. }
  595. if (rawmode) {
  596. if (b & 0x80) {
  597. if (oldsync < j) {
  598. syncs[synccnt++] = j;
  599. oldsync = j + 300;
  600. }
  601. }
  602. if (synccnt >= 3 && j > oldsync)
  603. break;
  604. }
  605. b = threshtab[b & 0x7f];
  606. tt1 = (tt1 << b) + 1;
  607. tt2 += b;
  608. if (tt2 >= 16) {
  609. tt2 -= 16;
  610. mfmbuf[j++] = tt1 >> (tt2 + 8);
  611. mfmbuf[j++] = tt1 >> tt2;
  612. }
  613. i++;
  614. }
  615. write_log ("cyl=%d, side=%d, length %d, syncs %d\n", d->track, side, j, synccnt);
  616. if (rawmode) {
  617. if (synccnt >= 3) {
  618. p1 = scantrack (mfmbuf + syncs[1], mfmbuf + syncs[2], &bytes, &bits);
  619. if (p1) {
  620. j = 0;
  621. for (i = 0; i < bytes + 2; i+=2) {
  622. mfm[j++] = (p1[i] << 8) | p1[i + 1];
  623. }
  624. return bytes * 8 + bits;
  625. }
  626. }
  627. } else {
  628. return isamigatrack (mfmbuf, mfmbuf + j, mfm, d->track * 2 + side);
  629. }
  630. return 0;
  631. }
  632. int catweasel_read(catweasel_drive *d, int side, int clock, int rawmode)
  633. {
  634. int iobase = d->contr->iobase;
  635. CWSetCReg(d->contr, d->sel, 0);
  636. if(d->contr->type == CATWEASEL_TYPE_MK1) {
  637. CWSetCReg(d->contr, 1<<2, (!side)<<2); /* set disk side */
  638. inb(iobase+1); /* ra reset */
  639. outb(clock*128, iobase+3);
  640. inb(iobase+1);
  641. inb(iobase+0);
  642. // inb(iobase+0);
  643. // outb(0, iobase+3); /* don't store index pulse */
  644. inb(iobase+1);
  645. inb(iobase+7); /* start reading */
  646. sleep_millis(rawmode ? 550 : 225);
  647. outb(0, iobase+1); /* stop reading, don't reset RAM pointer */
  648. outb(128, iobase+0); /* add data end mark */
  649. outb(128, iobase+0);
  650. inb(iobase+1); /* Reset RAM pointer */
  651. } else {
  652. CWSetCReg(d->contr, 1<<6, (!side)<<6); /* set disk side */
  653. outb(0, iobase + 0xe4); /* Reset memory pointer */
  654. switch(clock) {
  655. case 0: /* 28MHz */
  656. outb(128, iobase + 0xec);
  657. break;
  658. case 1: /* 14MHz */
  659. outb(0, iobase + 0xec);
  660. break;
  661. }
  662. inb(iobase + 0xe0);
  663. inb(iobase + 0xe0);
  664. outb(0, iobase + 0xec); /* no IRQs, no MFM predecode */
  665. inb(iobase + 0xe0);
  666. outb(0, iobase + 0xec); /* don't store index pulse */
  667. outb(0, iobase + 0xe4); /* Reset memory pointer */
  668. inb(iobase + 0xf0); /* start reading */
  669. sleep_millis(rawmode ? 550 : 225);
  670. inb(iobase + 0xe4); /* stop reading, don't reset RAM pointer */
  671. outb(255, iobase + 0xe0); /* add data end mark */
  672. outb(254, iobase + 0xe0); /* add data end mark */
  673. outb(253, iobase + 0xe0); /* add data end mark */
  674. outb(252, iobase + 0xe0); /* add data end mark */
  675. outb(251, iobase + 0xe0); /* add data end mark */
  676. outb(0, iobase + 0xe4); /* Reset memory pointer */
  677. }
  678. CWSetCReg(d->contr, 0, d->sel);
  679. return 1;
  680. }
  681. #endif